Index: libs/libmythtv/NuppelVideoPlayer.cpp
===================================================================
--- libs/libmythtv/NuppelVideoPlayer.cpp	(revision 11680)
+++ libs/libmythtv/NuppelVideoPlayer.cpp	(working copy)
@@ -204,6 +204,7 @@
       audio_samplerate(44100),      audio_stretchfactor(1.0f),
       // Picture-in-Picture
       pipplayer(NULL), setpipplayer(NULL), needsetpipplayer(false),
+      ispip(false), softwareScalingPIP(false),
       // Preview window support
       argb_buf(NULL),               argb_size(0,0),
       yuv2argb_conv(yuv2rgb_init_mmx(32, MODE_RGB)),
@@ -294,7 +295,8 @@
 
     if (m_playbackinfo)
     {
-        m_playbackinfo->MarkAsInUse(false);
+        if (!ispip)
+            m_playbackinfo->MarkAsInUse(false);
         delete m_playbackinfo;
     }
 
@@ -540,11 +542,27 @@
             return false;
         }
 
+        if (ispip)
+        {
+            if (m_tv)
+                videoOutput->SetAsPIP(kPIPOnTV);
+            else
+                videoOutput->SetAsPIP(kPIPOn);
+        }
+
         if (!videoOutput->Init(video_width, video_height, video_aspect,
                                widget->winId(), 0, 0, widget->width(),
                                widget->height(), 0))
         {
             errored = true;
+        }
+        
+        if (errored && !videoOutput->hasXVAcceleration() && ispip)
+        {
+            softwareScalingPIP = true;
+            delete videoOutput;
+            videoOutput = NULL;
+            errored = true;
             return false;
         }
 
@@ -636,7 +654,7 @@
 {
     QString errMsg = QString::null;
 
-    if ((audio_bits <= 0) || (audio_channels <= 0) || (audio_samplerate <= 0))
+    if (ispip || (audio_bits <= 0) || (audio_channels <= 0) || (audio_samplerate <= 0))
     {
         VERBOSE(VB_IMPORTANT, LOC +
                 QString("Disabling Audio, params(%1,%2,%3)")
@@ -2589,6 +2607,8 @@
         {
             pipplayer = setpipplayer;
             needsetpipplayer = false;
+            if (m_tv)
+                m_tv->PIPPlayerWake();
         }
 
         if (ringBuffer->isDVD())
@@ -3049,15 +3069,17 @@
 
     if (!InitVideo())
     {
-        qApp->lock();
-        DialogBox *dialog = new DialogBox(gContext->GetMainWindow(),
+        if (!ispip)
+        {
+            qApp->lock();
+            DialogBox *dialog = new DialogBox(gContext->GetMainWindow(),
                                    QObject::tr("Unable to initialize video."));
-        dialog->AddButton(QObject::tr("Return to menu."));
-        dialog->exec();
-        delete dialog;
+            dialog->AddButton(QObject::tr("Return to menu."));
+            dialog->exec();
+            delete dialog;
+            qApp->unlock();
+        }
 
-        qApp->unlock();
-
         if (audioOutput)
         {
             delete audioOutput;
@@ -3656,8 +3678,8 @@
     int numFrames = totalFrames;
 
     if (m_playbackinfo->GetTranscodedStatus() != TRANSCODING_COMPLETE)
-        numFrames = (m_playbackinfo->endts.toTime_t() -
-                    m_playbackinfo->recstartts.toTime_t()) * video_frame_rate;
+        numFrames = (int)((m_playbackinfo->endts.toTime_t() -
+                    m_playbackinfo->recstartts.toTime_t()) * video_frame_rate);
 
     int offset = (int) round(0.14 * (numFrames / video_frame_rate));
 
Index: libs/libmythtv/libmythtv.pro
===================================================================
--- libs/libmythtv/libmythtv.pro	(revision 11680)
+++ libs/libmythtv/libmythtv.pro	(working copy)
@@ -216,9 +216,9 @@
 
     # Video playback
     HEADERS += tv_play.h                NuppelVideoPlayer.h
-    HEADERS += DVDRingBuffer.h
+    HEADERS += DVDRingBuffer.h          pipplayer.h
     SOURCES += tv_play.cpp              NuppelVideoPlayer.cpp
-    SOURCES += DVDRingBuffer.cpp
+    SOURCES += DVDRingBuffer.cpp        pipplayer.cpp
 
     # Text subtitle parser
     HEADERS += textsubtitleparser.h     xine_demux_sputext.h
Index: libs/libmythtv/tv_play.h
===================================================================
--- libs/libmythtv/tv_play.h	(revision 11680)
+++ libs/libmythtv/tv_play.h	(working copy)
@@ -33,6 +33,7 @@
 class OSDListTreeType;
 class OSDGenericTree;
 class LiveTVChain;
+class PIPPlayer;
 
 typedef QValueVector<QString>    str_vec_t;
 typedef QMap<QString,QString>    InfoMap;
@@ -126,10 +127,10 @@
     void ShowNoRecorderDialog(void);
     void FinishRecording(void);
     void AskAllowRecording(const QStringList&, int, bool);
+    void PIPPlayerWake(void) { pipplayerCond.wakeAll(); }
     void PromptStopWatchingRecording(void);
     void PromptDeleteRecording(QString title);
     
-
     // Boolean queries
 
     /// Returns true if we are playing back a non-LiveTV recording.
@@ -193,6 +194,7 @@
     void SleepEndTimer(void);
     void TreeMenuEntered(OSDListTreeType *tree, OSDGenericTree *item);
     void TreeMenuSelected(OSDListTreeType *tree, OSDGenericTree *item);
+    void PIPVideoTimer(void);
 
   protected:
     void doEditSchedule(int editType = kScheduleProgramGuide);
@@ -320,8 +322,6 @@
 
     void SetupPlayer(bool isWatchingRecording);
     void TeardownPlayer(void);
-    void SetupPipPlayer(void);
-    void TeardownPipPlayer(void);
     
     void HandleStateChange(void);
     bool InStateChange(void) const;
@@ -331,8 +331,9 @@
     void TogglePIPView(void);
     void ToggleActiveWindow(void);
     void SwapPIP(void);
+    TVState GetPIPState(PIPPlayer *pip);
     void SwapPIPSoon(void) { needToSwapPIP = true; }
-
+    
     void ToggleAutoExpire(void);
 
     void BrowseStart(void);
@@ -529,14 +530,16 @@
 
     // Video Players
     NuppelVideoPlayer *nvp;
-    NuppelVideoPlayer *pipnvp;
+    PIPPlayer  *pipplayer; 
     NuppelVideoPlayer *activenvp;  ///< Player to which LiveTV events are sent
 
+    //PIP Stuff
+    QTimer *pipVideoTimer;
+    QWaitCondition pipplayerCond;
+
     // Remote Encoders
     /// Main recorder
     RemoteEncoder *recorder;
-    /// Picture-in-Picture recorder
-    RemoteEncoder *piprecorder;
     /// Recorder to which LiveTV events are being sent
     RemoteEncoder *activerecorder;
     /// Main recorder to use after a successful SwitchCards() call.
@@ -546,13 +549,11 @@
 
     // LiveTVChain
     LiveTVChain *tvchain;
-    LiveTVChain *piptvchain;
     QStringList tvchainUpdate;
     QMutex tvchainUpdateLock;
 
     // RingBuffers
     RingBuffer *prbuffer;
-    RingBuffer *piprbuffer;
     RingBuffer *activerbuffer; ///< Ringbuffer to which LiveTV events are sent
 
     // OSD info
@@ -589,9 +590,6 @@
     pthread_t event;
     /// Video decoder thread, runs nvp's NuppelVideoPlayer::StartPlaying().
     pthread_t decode;
-    /// Picture-in-Picture video decoder thread,
-    /// runs pipnvp's NuppelVideoPlayer::StartPlaying().
-    pthread_t pipdecode;
 
     /// Condition to signal that the Event thread is up and running
     QWaitCondition mainLoopCond;
Index: libs/libmythtv/pipplayer.h
===================================================================
--- libs/libmythtv/pipplayer.h	(revision 0)
+++ libs/libmythtv/pipplayer.h	(revision 0)
@@ -0,0 +1,68 @@
+#ifndef PIPPLAYER_H
+#define PIPPLAYER_H
+
+#include <qpainter.h>
+#include "NuppelVideoPlayer.h"
+#include "RingBuffer.h"
+#include "programinfo.h"
+#include "livetvchain.h"
+#include "remoteencoder.h"
+
+class RingBuffer;
+class ProgramInfo;
+class LiveTVChain;
+class RemoteEncoder;
+class NuppelVideoPlayer;
+
+class PIPPlayer
+{
+    public:
+        PIPPlayer(void);
+        ~PIPPlayer(void);
+        static PIPPlayer *Create(const QRect &rect);
+        static PIPPlayer * Create(NuppelVideoPlayer *parentnvp, int location);
+        bool StartPlaying(ProgramInfo *rec = NULL, 
+                            bool piptype = false,
+                            bool nullvideo = false);
+        void StopPlaying();
+        bool IsPlaying(void) { return (pipnvp && pipnvp->IsPlaying()); }
+        void SetFrameRate(double fps);
+        bool IsSameProgram(ProgramInfo *rec);
+        RingBuffer          *GetRingBuffer(void) { return piprbuffer; }
+        RemoteEncoder       *GetRecorder(void) { return piprecorder; }
+        LiveTVChain         *GetLiveTVChain(void) { return piptvchain; }
+        NuppelVideoPlayer   *GetNVP(void) { return pipnvp; }
+        ProgramInfo         *GetProgramInfo(void) { return piprecinfo; }
+        void SetRingBuffer(RingBuffer *rbuffer);
+        void SetLiveTVChain(LiveTVChain *tvchain);
+        void SetRecorder(RemoteEncoder  *recorder);
+        void SetProgramInfo(ProgramInfo *pginfo);
+        void SetReinit(bool change) { reinit = change; }
+        bool IsLiveTV(void) { return islivetv; }
+        bool IsHidden(void);
+        void Hide(void);
+        void Show(void);
+        bool UsingNullVideo(void) { return using_nullvideo; }
+        void DisplaySoftwareScaledImage(void);
+        
+
+    private:
+        bool StartRecorder(RemoteEncoder *rec, int maxWait);
+        void Reinitialize(void);
+        void Init(QRect rect, QString name);
+
+    private:
+        RemoteEncoder *piprecorder;
+        RingBuffer *piprbuffer;
+        LiveTVChain  *piptvchain;
+        ProgramInfo *piprecinfo;
+        NuppelVideoPlayer *pipnvp;
+        pthread_t videoThread;
+        pthread_t pipdecode;
+        QWidget *pipWindow;
+        bool islivetv;
+        bool reinit;
+        bool using_nullvideo;
+};
+
+#endif
Index: libs/libmythtv/NuppelVideoPlayer.h
===================================================================
--- libs/libmythtv/NuppelVideoPlayer.h	(revision 11680)
+++ libs/libmythtv/NuppelVideoPlayer.h	(working copy)
@@ -128,7 +128,8 @@
 
     // Sets
     void SetParentWidget(QWidget *widget)     { parentWidget = widget; }
-    void SetAsPIP(void)                       { SetNoAudio(); SetNullVideo(); }
+    void SetAsPIP(bool setNullVideo)         
+        { if (setNullVideo) SetNullVideo(); ispip = true; }
     void SetNullVideo(void)                   { using_null_videoout = true; }
     void SetFileName(QString lfilename)       { filename = lfilename; }
     void SetExactSeeks(bool exact)            { exactseeks = exact; }
@@ -140,7 +141,7 @@
     void SetVideoFilters(QString &filters)    { videoFilterList = filters; }
     void SetFramesPlayed(long long played)    { framesPlayed = played; }
     void SetEof(void)                         { eof = true; }
-    void SetPipPlayer(NuppelVideoPlayer *pip)
+    void SetPIPPlayer(NuppelVideoPlayer *pip)
         { setpipplayer = pip; needsetpipplayer = true; }
     void SetRecorder(RemoteEncoder *recorder);
     void SetParentPlayer(TV *tv)             { m_tv = tv; }
@@ -193,7 +194,8 @@
     bool    GetRawAudioState(void) const;
     bool    GetLimitKeyRepeat(void) const     { return limitKeyRepeat; }
     bool    GetEof(void) const                { return eof; }
-    bool    PipPlayerSet(void) const          { return !needsetpipplayer; }
+    bool    PIPPlayerSet(void) const          { return !needsetpipplayer; }
+    bool    HasPIPPlayer(void) const          { return (pipplayer != NULL); }
     bool    IsErrored(void) const             { return errored; }
     bool    IsPlaying(void) const             { return playing; }
     bool    AtNormalSpeed(void) const         { return next_normal_speed; }
@@ -203,6 +205,7 @@
     bool    PlayingSlowForPrebuffer(void) const { return m_playing_slower; }
     bool    HasAudioIn(void) const            { return !no_audio_in; }
     bool    HasAudioOut(void) const           { return !no_audio_out; }
+    bool    PIPSoftwareScaling(void)          { return softwareScalingPIP; }
 
     // Complicated gets
     long long CalcMaxFFTime(long long ff, bool setjump = true) const;
@@ -223,6 +226,7 @@
     void StartPlaying(void);
     void ResetPlaying(void);
     void StopPlaying(void) { killplayer = true; decoder_thread_alive = false; }
+        
 
     // Pause stuff
     void PauseDecoder(void);
@@ -670,6 +674,8 @@
     NuppelVideoPlayer *pipplayer;
     NuppelVideoPlayer *setpipplayer;
     bool needsetpipplayer;
+    bool ispip;
+    bool softwareScalingPIP;
 
     // Preview window support
     unsigned char      *argb_buf;
Index: libs/libmythtv/tv_play.cpp
===================================================================
--- libs/libmythtv/tv_play.cpp	(revision 11680)
+++ libs/libmythtv/tv_play.cpp	(working copy)
@@ -39,6 +39,7 @@
 #include "DVDRingBuffer.h"
 #include "datadirect.h"
 #include "sourceutil.h"
+#include "pipplayer.h"
 
 #ifndef HAVE_ROUND
 #define round(x) ((int) ((x) + 0.5))
@@ -462,14 +463,16 @@
       lastProgram(NULL), jumpToProgram(false),
       inPlaylist(false), underNetworkControl(false),
       // Video Players
-      nvp(NULL), pipnvp(NULL), activenvp(NULL),
+      nvp(NULL), pipplayer(NULL), activenvp(NULL),
+      // PIP Stuff
+      pipVideoTimer(new QTimer(this)),
       // Remote Encoders
-      recorder(NULL), piprecorder(NULL), activerecorder(NULL),
+      recorder(NULL), activerecorder(NULL),
       switchToRec(NULL), lastrecordernum(-1),
       // LiveTVChain
-      tvchain(NULL), piptvchain(NULL),
+      tvchain(NULL),
       // RingBuffers
-      prbuffer(NULL), piprbuffer(NULL), activerbuffer(NULL),
+      prbuffer(NULL), activerbuffer(NULL),
       // OSD info
       dialogname(""), treeMenu(NULL), udpnotify(NULL), osdlock(true),
       // LCD Info
@@ -502,6 +505,7 @@
     connect(muteTimer,        SIGNAL(timeout()), SLOT(UnMute()));
     connect(keyrepeatTimer,   SIGNAL(timeout()), SLOT(KeyRepeatOK()));
     connect(sleepTimer,       SIGNAL(timeout()), SLOT(SleepEndTimer()));
+    connect(pipVideoTimer,    SIGNAL(timeout()), SLOT(PIPVideoTimer()));
 }
 
 /** \fn TV::Init(bool)
@@ -679,13 +683,6 @@
         delete tvchain;
     }
 
-    if (piptvchain)
-    {
-        VERBOSE(VB_IMPORTANT, LOC + "Deleting PiP TV Chain in destructor");
-        piptvchain->DestroyChain();
-        delete piptvchain;
-    }    
-
     if (ddMapLoaderRunning)
     {
         pthread_join(ddMapLoader, NULL);
@@ -699,6 +696,14 @@
             pthread_detach(ddMapLoader);
         }
     }
+
+    if (pipVideoTimer)
+    {
+        pipVideoTimer->disconnect(this);
+        pipVideoTimer->deleteLater();
+        pipVideoTimer = NULL;
+    }
+        
 }
 
 TVState TV::GetState(void) const
@@ -1379,13 +1384,6 @@
             prbuffer->Pause();
             prbuffer->WaitForPause();
         }
-
-        if (piprbuffer)
-        {
-            piprbuffer->StopReads();
-            piprbuffer->Pause();
-            piprbuffer->WaitForPause();
-        }
     }
 
     if (stopPlayers)
@@ -1393,9 +1391,6 @@
         VERBOSE(VB_PLAYBACK, LOC + "StopStuff(): stopping player[s] (1/2)");
         if (nvp)
             nvp->StopPlaying();
-
-        if (pipnvp)
-            pipnvp->StopPlaying();
     }
 
     if (stopRecorders)
@@ -1403,9 +1398,6 @@
         VERBOSE(VB_PLAYBACK, LOC + "StopStuff(): stopping recorder[s]");
         if (recorder)
             recorder->StopLiveTV();
-
-        if (piprecorder)
-            piprecorder->StopLiveTV();
     }
 
     if (stopPlayers)
@@ -1413,9 +1405,11 @@
         VERBOSE(VB_PLAYBACK, LOC + "StopStuff(): stopping player[s] (2/2)");
         if (nvp)
             TeardownPlayer();
-
-        if (pipnvp)
-            TeardownPipPlayer();
+        if (pipplayer)
+        {
+            delete pipplayer;
+            pipplayer = NULL;
+        }
     }
     VERBOSE(VB_PLAYBACK, LOC + "StopStuff() -- end");
 }
@@ -1497,28 +1491,6 @@
     return filters;
 }
 
-void TV::SetupPipPlayer(void)
-{
-    if (pipnvp)
-    {
-        VERBOSE(VB_IMPORTANT, LOC_ERR +
-                "Attempting to setup a PiP player, but it already exists.");
-        return;
-    }
-
-    pipnvp = new NuppelVideoPlayer("PIP player");
-    pipnvp->SetAsPIP();
-    pipnvp->SetRingBuffer(piprbuffer);
-    pipnvp->SetRecorder(piprecorder);
-    pipnvp->SetAudioInfo(gContext->GetSetting("AudioOutputDevice"),
-                         gContext->GetSetting("PassThruOutputDevice"),
-                         gContext->GetNumSetting("AudioSampleRate", 44100));
-    pipnvp->SetExactSeeks(gContext->GetNumSetting("ExactSeeking", 0));
-    pipnvp->SetLiveTVChain(piptvchain);
-
-    pipnvp->SetLength(playbackLen);
-}
-
 void TV::TeardownPlayer(void)
 {
     if (nvp)
@@ -1568,12 +1540,6 @@
         prbuffer = activerbuffer = NULL;
     }
 
-    if (piprbuffer)
-    {
-        delete piprbuffer;
-        piprbuffer = NULL;
-    }
-
     if (tvchain)
     {
         tvchain->DestroyChain();
@@ -1582,45 +1548,6 @@
     }
 }
 
-void TV::TeardownPipPlayer(void)
-{
-    if (pipnvp)
-    {
-        if (activerecorder == piprecorder)
-            ToggleActiveWindow();
-
-        osdlock.lock(); // prevent UpdateOSDSignal from using osd...
-        NuppelVideoPlayer *xnvp = pipnvp;
-        pthread_t          xdec = pipdecode;
-        pipnvp = NULL;
-        osdlock.unlock();
-
-        // NVP may try to get qapp lock if there is an error,
-        // so we need to do this outside of the osdlock.
-        pthread_join(xdec, NULL);
-        delete xnvp;
-    }
-
-    if (piprecorder)
-    {
-        delete piprecorder;
-        piprecorder = NULL;
-    }
-
-    if (piprbuffer)
-    {
-        delete piprbuffer;
-        piprbuffer = NULL;
-    }
-
-    if (piptvchain)
-    {
-        piptvchain->DestroyChain();
-        delete piptvchain;
-        piptvchain = NULL;
-    }
-}
-
 void *TV::EventThread(void *param)
 {
     TV *thetv = (TV *)param;
@@ -1686,11 +1613,13 @@
                         if (nvp->GetTVChain())
                             nvp->CheckTVChain();
                     }
-                    if (piptvchain && pipnvp && *it == piptvchain->GetID())
+                    if (pipplayer && pipplayer->IsLiveTV()
+                            && *it == pipplayer->GetLiveTVChain()->GetID())
                     {
+                        LiveTVChain *piptvchain = pipplayer->GetLiveTVChain();
                         piptvchain->ReloadAll();
-                        if (pipnvp->GetTVChain())
-                            pipnvp->CheckTVChain();
+                        if (pipplayer->GetNVP()->GetTVChain())
+                            pipplayer->GetNVP()->CheckTVChain();
                     }
                 }
                 tvchainUpdate.clear();
@@ -1752,6 +1681,9 @@
             wantsToQuit = true;
         }
 
+        if (pipplayer && !pipplayer->IsPlaying())
+            TogglePIPView();
+
         if (StateIsPlaying(internalState))
         {
 #ifdef USING_VALGRIND
@@ -1859,7 +1791,7 @@
             prevChan = tmp;
             pseudoLiveTVState[i] = kPseudoRecording;
 
-            if (i && pipnvp)
+            if (i && pipplayer)
                 TogglePIPView();
         }
 
@@ -1976,6 +1908,8 @@
         {
             if (nvp)
                 nvp->ExposeEvent();
+            if (pipplayer && pipplayer->GetNVP())
+                pipplayer->GetNVP()->ExposeEvent();
             return true;
         }
         case MythEvent::MythEventMessage:
@@ -2558,6 +2492,12 @@
             DoQueueTranscode("Low Quality");
         else if (action == "PLAY")
             DoPlay();
+        else if (action == "TOGGLEPIPMODE")
+            TogglePIPView();
+        else if (action == "TOGGLEPIPWINDOW")
+            ToggleActiveWindow();
+        else if (action == "SWAPPIP")
+            SwapPIPSoon();
         else if (action == "PAUSE") 
             DoPause();
         else if (action == "SPEEDINC" && !activerbuffer->InDVDMenuOrStillFrame())
@@ -2926,12 +2866,6 @@
                 SwitchCards();
             else if (action == "GUIDE")
                 EditSchedule(kScheduleProgramGuide);
-            else if (action == "TOGGLEPIPMODE")
-                TogglePIPView();
-            else if (action == "TOGGLEPIPWINDOW")
-                ToggleActiveWindow();
-            else if (action == "SWAPPIP")
-                SwapPIPSoon();
             else if (action == "TOGGLEBROWSE")
                 BrowseStart();
             else if (action == "PREVCHAN")
@@ -3213,213 +3147,255 @@
     }
 }
 
+void TV::PIPVideoTimer(void)
+{
+    if (pipplayer && pipplayer->IsPlaying())
+        pipplayer->SetFrameRate(10.0);
+}
+
 void TV::TogglePIPView(void)
 {
-    if (!pipnvp)
+    if (!pipplayer && !activenvp->HasPIPPlayer())
     {
-        RemoteEncoder *testrec = RemoteRequestRecorder();
-        
-        if (!testrec || !testrec->IsValidRecorder())
-        {
-            VERBOSE(VB_IMPORTANT, LOC_ERR + "PiP failed to locate recorder");
-            if (testrec)
-                delete testrec;
+        int pip_location = gContext->GetNumSetting("PIPLocation", 0);
+        QRect rect = activenvp->getVideoOutput()->GetPIPRect(pip_location);
+        pipplayer = PIPPlayer::Create(rect);
+        if (!pipplayer)
             return;
-        }
-
-        testrec->Setup();
-
-        piptvchain = new LiveTVChain();
-        piptvchain->InitializeNewChain("PIP"+gContext->GetHostName());
-        testrec->SpawnLiveTV(piptvchain->GetID(), true);
-        piptvchain->ReloadAll();
-        playbackinfo = piptvchain->GetProgramAt(-1);
-        if (!playbackinfo)
-        {
-            VERBOSE(VB_IMPORTANT, LOC_ERR + "PiP not successfully started");
-            delete testrec;
-            piptvchain->DestroyChain();
-            delete piptvchain;
-            piptvchain = NULL;
-        }
+        pipplayer->Hide();
+        pipplayer->StartPlaying(NULL, true);
+        if (pipplayer->IsPlaying())
+            pipplayer->Show();
         else
         {
-            QString playbackURL = playbackinfo->GetPlaybackURL();
-
-            piptvchain->SetProgram(playbackinfo);
-            piprbuffer = new RingBuffer(playbackURL, false);
-            piprbuffer->SetLiveMode(piptvchain);
-        }
-
-        piprecorder = testrec;
-
-        if (StartRecorder(piprecorder, -1))
-        {
-            SetupPipPlayer();
-            VERBOSE(VB_PLAYBACK, "PiP Waiting for NVP");
-            pthread_create(&pipdecode, NULL, SpawnDecode, pipnvp);
-            while (!pipnvp->IsPlaying() && pipnvp->IsDecoderThreadAlive())
+            if (pipplayer->GetNVP() &&
+                pipplayer->GetNVP()->PIPSoftwareScaling())
             {
-                piptvchain->ReloadAll();
-                usleep(5000);
-            }
-            VERBOSE(VB_PLAYBACK, "PiP NVP Started");
-
-            if (pipnvp->IsDecoderThreadAlive())
-                nvp->SetPipPlayer(pipnvp);
+                pipplayer->StartPlaying(NULL, true, true);
+                if (pipplayer->IsPlaying())
+                    activenvp->SetPIPPlayer(pipplayer->GetNVP());
+                pipplayerCond.wait();
+                pipVideoTimer->start(2000);
+            } 
             else
             {
-                VERBOSE(VB_IMPORTANT, LOC_ERR + "PiP player failed to start");
-                osdlock.lock();
-                delete pipnvp;
-                pipnvp = NULL;
-                osdlock.unlock();
-                TeardownPipPlayer();
+                delete pipplayer;
+                pipplayer = NULL;
             }
         }
-        else
-        {
-            VERBOSE(VB_IMPORTANT, LOC_ERR + "PiP recorder failed to start");
-            TeardownPipPlayer();
-        }
     }
     else
     {
-        if (activenvp != nvp)
-            ToggleActiveWindow();
-
-        nvp->SetPipPlayer(NULL);
-        while (!nvp->PipPlayerSet())
-            usleep(50);
-
-        piprbuffer->StopReads();
-        piprbuffer->Pause();
-        while (!piprbuffer->isPaused())
-            usleep(50);
-
-        pipnvp->StopPlaying();
-
-        piprecorder->StopLiveTV();
-
-        TeardownPipPlayer();
-
-        SetPseudoLiveTV(1, NULL, kPseudoNormalLiveTV);
+        activenvp->SetPIPPlayer(NULL);
+        pipplayerCond.wait(); 
+        delete pipplayer;
+        pipplayer = NULL;
+        pipVideoTimer->stop();
     }
 }
 
 void TV::ToggleActiveWindow(void)
 {
-    if (!pipnvp)
-        return;
+    /* its broken. needs more work. need to keep track of the
+     * different programinfos for each nvp
+     * working on it
+     */
+   /*
+   if (!pipplayer || !pipplayer->IsPlaying())
+       return;
+   
+   lockTimerOn = false;
+   LiveTVChain *piptvchain = NULL;
+   
+   if (activenvp == nvp)
+   {
+       
+       activenvp      = pipplayer->GetNVP();
+       activerbuffer  = pipplayer->GetRingBuffer();
+       activerecorder = pipplayer->GetRecorder();
+       piptvchain     = pipplayer->GetLiveTVChain();
+   }
+   else
+   {
+       activenvp      = nvp;
+       activerbuffer  = prbuffer;
+       activerecorder = recorder;
+   }
 
-    lockTimerOn = false;
-    if (activenvp == nvp)
-    {
-        activenvp = pipnvp;
-        activerbuffer = piprbuffer;
-        activerecorder = piprecorder;
-    }
-    else
-    {
-        activenvp = nvp;
-        activerbuffer = prbuffer;
-        activerecorder = recorder;
-    }
-    LiveTVChain *chain = (activenvp == nvp) ? tvchain : piptvchain;
-    ProgramInfo *pginfo = chain->GetProgramAt(-1);
-    if (pginfo)
-    {
-        SetCurrentlyPlaying(pginfo);
-        delete pginfo;
-    }
+   if (activerecorder)
+   {
+        LiveTVChain *chain  = (activenvp == nvp) ? tvchain : piptvchain;
+        ProgramInfo *pginfo = chain->GetProgramAt(-1);
+        if (pginfo)
+        {
+            SetCurrentlyPlaying(pginfo);
+            delete pginfo;
+        }
+   }
+
+   */
 }
 
+
 struct pip_info
 {
     RingBuffer    *buffer;
     RemoteEncoder *recorder;
     LiveTVChain   *chain;
     long long      frame;
+    ProgramInfo   *pginfo;
 };
 
 void TV::SwapPIP(void)
 {
-    if (!pipnvp || !piptvchain || !tvchain) 
+    if (!pipplayer)
+        // TODO print something on OSD informing use that PIP swap cannot be done
         return;
 
-    lockTimerOn = false;
+    bool use_nullvideo = pipplayer->UsingNullVideo();
+    bool pipislivetv = StateIsLiveTV(internalState);
+    
+    if (activenvp != nvp)
+        ToggleActiveWindow();
 
-    struct pip_info main, pip;
-    main.buffer   = prbuffer;
-    main.recorder = recorder;
-    main.chain    = tvchain;
-    main.frame    = nvp->GetFramesPlayed();
-    pip.buffer    = piprbuffer;
-    pip.recorder  = piprecorder;
-    pip.chain     = piptvchain;
-    pip.frame     = pipnvp->GetFramesPlayed();
+    if (paused)
+        DoPause();
+    StopFFRew();
+    NormalSpeed();
 
+   if (playbackinfo)
+       playbackinfo->setIgnoreBookmark(false);
+   if (pipplayer->GetProgramInfo())
+       pipplayer->GetProgramInfo()->setIgnoreBookmark(false);
+   
+   // set the bookmark
+    activenvp->SetBookmark();
+    pipplayer->GetNVP()->SetBookmark();
+    
+    struct pip_info main, pip;
+    main.buffer      = prbuffer;
+    main.recorder    = recorder;
+    main.chain       = tvchain;
+    main.frame       = nvp->GetFramesPlayed(); 
+    if (StateIsPlaying(internalState))
+        main.pginfo = new ProgramInfo(*playbackinfo);
+    else
+        main.pginfo = NULL;
+    
+    pip.buffer       = pipplayer->GetRingBuffer();
+    pip.recorder     = pipplayer->GetRecorder();
+    pip.chain        = pipplayer->GetLiveTVChain();
+    pip.frame        = pipplayer->GetNVP()->GetFramesPlayed();
+    if (!pipplayer->IsLiveTV())
+        pip.pginfo   = new ProgramInfo(*pipplayer->GetProgramInfo());
+    else
+        pip.pginfo   = NULL;
+  
+    pipplayer->Hide();
+    if (use_nullvideo)
+    {
+        activenvp->SetPIPPlayer(NULL);
+        pipplayerCond.wait();
+    }
+    pipplayer->SetReinit(false);
+    pipplayer->StopPlaying();
+    
     prbuffer->Pause();
     prbuffer->WaitForPause();
 
-    piprbuffer->Pause();
-    piprbuffer->WaitForPause();
-
     nvp->StopPlaying();
-    pipnvp->StopPlaying();
+
     {
-        QMutexLocker locker(&osdlock); // prevent UpdateOSDSignal using osd...
+        QMutexLocker locker(&osdlock); // prevent UpdateOSDSignal using osd..
         pthread_join(decode, NULL);
         delete nvp;
         nvp = NULL;
-        pthread_join(pipdecode, NULL);
-        delete pipnvp;
-        pipnvp = NULL;
     }
 
+    if (playbackinfo)
+        delete playbackinfo;
+   
     activerbuffer  = prbuffer = pip.buffer;
     activerecorder = recorder = pip.recorder;
     tvchain                   = pip.chain;
+    playbackinfo              = pip.pginfo;
+    internalState             = GetPIPState(pipplayer);
 
-    piprbuffer  = main.buffer;
-    piprecorder = main.recorder;
-    piptvchain  = main.chain;
-
+    pipplayer->SetRingBuffer(main.buffer);
+    pipplayer->SetRecorder(main.recorder);
+    pipplayer->SetLiveTVChain(main.chain);
+    pipplayer->SetProgramInfo(main.pginfo);
+    
+    VERBOSE(VB_PLAYBACK, QString("TV SwapPIP: New InternalState is %1")
+            .arg(StateToString(internalState)));
+    
     prbuffer->Seek(0, SEEK_SET);
     prbuffer->Unpause();
-    StartPlayer(false);
-    activenvp = nvp;
-    nvp->FastForward(pip.frame/recorder->GetFrameRate());
 
-    piprbuffer->Seek(0, SEEK_SET);
-    piprbuffer->Unpause();
-    SetupPipPlayer();
-    VERBOSE(VB_PLAYBACK, "PiP Waiting for NVP -- restart");
-    pthread_create(&pipdecode, NULL, SpawnDecode, pipnvp);
-    while (!pipnvp->IsPlaying() && pipnvp->IsDecoderThreadAlive())
+    if (internalState == kState_WatchingRecording)
+        StartPlayer(true);
+    else
+        StartPlayer(false);
+
+    activenvp = nvp;
+    usleep(10000);
+    if (tvchain)
+        nvp->FastForward(pip.frame/recorder->GetFrameRate());
+    
+    pipplayer->GetRingBuffer()->Seek(0, SEEK_SET);
+    pipplayer->GetRingBuffer()->Unpause();
+  
+    if (use_nullvideo)
     {
-        piptvchain->ReloadAll();
-        usleep(5000);
+        pipplayer->StartPlaying(main.pginfo, pipislivetv, true);
+        if (pipplayer->IsPlaying())
+            activenvp->SetPIPPlayer(pipplayer->GetNVP());
     }
-    VERBOSE(VB_PLAYBACK, "PiP NVP Started -- restart");
-    pipnvp->FastForward(pip.frame/piprecorder->GetFrameRate());
-
-    if (pipnvp->IsDecoderThreadAlive())
-        nvp->SetPipPlayer(pipnvp);
     else
+        pipplayer->StartPlaying(main.pginfo, pipislivetv);
+
+    if (pipplayer->IsPlaying())
     {
-        VERBOSE(VB_IMPORTANT, LOC_ERR + "PiP player failed to start");
-        TeardownPipPlayer();
+        if (!use_nullvideo)
+            pipplayer->Show();
+        if (pipplayer->GetLiveTVChain())
+        {
+            pipplayer->GetLiveTVChain()->ReloadAll();
+            usleep(5000);
+        }
     }
 
-    ProgramInfo *pginfo = tvchain->GetProgramAt(-1);
-    if (pginfo)
+    if (internalState == kState_WatchingLiveTV)
+        SetPseudoLiveTV(0, NULL, kPseudoNormalLiveTV);
+
+    if (pipplayer->IsLiveTV())
+        SetPseudoLiveTV(1, NULL, kPseudoNormalLiveTV);
+
+    if (pipplayer->GetLiveTVChain())
+        pipplayer->GetNVP()->FastForward(main.frame/pipplayer->GetRecorder()->GetFrameRate());
+
+    if (tvchain)
     {
-        SetCurrentlyPlaying(pginfo);
-        delete pginfo;
+        ProgramInfo *pginfo = tvchain->GetProgramAt(-1);
+        if (pginfo)
+        {
+            SetCurrentlyPlaying(pginfo);
+            delete pginfo;
+        }
     }
+    pipplayer->SetReinit(true);
 }
 
+TVState TV::GetPIPState(PIPPlayer *player)
+{
+    if (player->IsLiveTV())
+        return kState_WatchingLiveTV;
+    else if (RemoteGetRecordingStatus(player->GetProgramInfo(),0,0))
+        return kState_WatchingRecording;
+    else
+        return kState_WatchingPreRecorded;
+}
+
 void TV::DoPlay(void)
 {
     float time = 0.0;
@@ -3474,7 +3450,15 @@
     float time = 0.0;
 
     if (paused)
+    {
         activenvp->Play(normal_speed, true);
+        if (pipplayer && pipplayer->IsPlaying())
+        {
+            pipplayer->GetNVP()->Play(normal_speed, true);
+            pipplayer->SetFrameRate(24.0); // need to increase fps after pause.
+            pipVideoTimer->start(2000);
+        }
+    }
     else 
     {
         if (doing_ff_rew)
@@ -3485,6 +3469,11 @@
         }
         
         activenvp->Pause();
+        if (pipplayer && pipplayer->IsPlaying())
+        {
+            pipVideoTimer->stop();
+            pipplayer->GetNVP()->Pause();
+        }
     }
 
     paused = !paused;
@@ -3849,7 +3838,7 @@
 
     RemoteEncoder *testrec = NULL;
 
-    if (!StateIsLiveTV(GetState()) || (activenvp != nvp) || pipnvp)
+    if (!StateIsLiveTV(GetState()) || (activenvp != nvp) || pipplayer)
         return;
 
     if (/*chanid || */!channum.isEmpty())
@@ -5369,8 +5358,8 @@
                 menurunning = false;
                 AskAllowRecording(me->ExtraDataList(), timeuntil, hasrec);
             }
-            else if (piprecorder &&
-                     cardnum == piprecorder->GetRecorderNumber())
+            else if (pipplayer && pipplayer->GetRecorder() &&
+                     cardnum == pipplayer->GetRecorder()->GetRecorderNumber())
             {
                 VERBOSE(VB_GENERAL, LOC + "Disabling PiP for recording");
                 TogglePIPView();
@@ -5388,8 +5377,8 @@
                 wantsToQuit = false;
                 exitPlayer = true;
             }
-            else if (piprecorder &&
-                     cardnum == piprecorder->GetRecorderNumber())
+            else if (pipplayer && pipplayer->GetRecorder() &&
+                     cardnum == pipplayer->GetRecorder()->GetRecorderNumber())
             {
                 VERBOSE(VB_GENERAL, LOC + "Disabling PiP for QUIT_LIVETV");
                 TogglePIPView();
@@ -5405,7 +5394,8 @@
             uint s = (cardnum == recorder->GetRecorderNumber()) ? 0 : 1;
 
             if ((recorder    && cardnum == recorder->GetRecorderNumber()) ||
-                (piprecorder && cardnum == piprecorder->GetRecorderNumber()))
+                (pipplayer && pipplayer->GetRecorder() && 
+                 cardnum == pipplayer->GetRecorder()->GetRecorderNumber()))
             {
                 if (watch)
                 {
@@ -5414,7 +5404,7 @@
                     if (pi.FromStringList(list, 0))
                         SetPseudoLiveTV(s, &pi, kPseudoChangeChannel);
 
-                    if (!s && pipnvp)
+                    if (!s && pipplayer)
                         TogglePIPView();
                 }
                 else
@@ -6436,7 +6426,7 @@
 
     if (StateIsLiveTV(GetState()))
     {
-        bool freeRecorders = (pipnvp != NULL);
+        bool freeRecorders = (pipplayer != NULL);
         if (!freeRecorders)
             freeRecorders = RemoteGetFreeRecorderCount();
 
@@ -7076,6 +7066,10 @@
 {
     VERBOSE(VB_PLAYBACK, LOC + "UnpauseLiveTV()");
 
+    LiveTVChain *piptvchain = NULL;
+    if (pipplayer)
+        piptvchain = pipplayer->GetLiveTVChain();
+
     LiveTVChain *chain = (activenvp == nvp) ? tvchain : piptvchain;
 
     if (activenvp && chain)
Index: libs/libmythtv/videooutbase.cpp
===================================================================
--- libs/libmythtv/videooutbase.cpp	(revision 11680)
+++ libs/libmythtv/videooutbase.cpp	(working copy)
@@ -171,6 +171,7 @@
     pip_desired_display_size(160,128),  pip_display_size(0,0),
     pip_video_size(0,0),
     pip_tmp_buf(NULL),                  pip_scaling_context(NULL),
+    piptype(kPIPOff),
 
     // Video resizing (for ITV)
     vsz_enabled(false),
@@ -253,7 +254,8 @@
 
     db_vdisp_profile->SetInput(video_dim);
 
-    letterbox  = db_letterbox;
+    if (piptype == kPIPOff)
+        letterbox  = db_letterbox;
 
     VideoAspectRatioChanged(aspect); // apply aspect ratio and letterbox mode
 
@@ -1044,7 +1046,96 @@
 
     db_pict_attr[attributeType] = newValue;
 }
+/*
+ * \brief Determines PIP Window size and Position.
+ */
+QRect VideoOutput::GetPIPRect(int location, NuppelVideoPlayer *pipplayer)
+{
+    
+    int tmph;
+    int tmpw;
+    int letterXadj  = 0;
+    int letterYadj  = 0;
+    float letterAdj = 1.0f;
+    int xpos = 0;
+    int ypos = 0;
+    int frame_height;
+    int frame_width;
+   
+    if (pipplayer)
+    {
+        frame_height = video_dim.height();
+        frame_width  = video_dim.width();
+    }
+    else
+    {
+        frame_height = display_visible_rect.height();
+        frame_width  = display_visible_rect.width();
+    }
+    float pipVideoAspect;
+    uint pipVideoWidth;
+    uint pipVideoHeight;
+    
+    if (pipplayer)
+    {
+        pipVideoAspect = pipplayer->GetVideoAspect();
+        pipVideoWidth  = pipplayer->GetVideoWidth();
+        pipVideoHeight = pipplayer->GetVideoHeight();
+    }
+    
+    if  (pipplayer && letterbox != kLetterbox_Off)
+    {
+        letterXadj = max(-display_video_rect.left(), 0);
+        float xadj = (float) video_rect.width() / display_visible_rect.width();
+        letterXadj = (int) (letterXadj * xadj);
 
+        float yadj = (float)video_rect.height() / display_visible_rect.height();
+        letterYadj = max(-display_video_rect.top(), 0);
+        letterYadj = (int) (letterYadj * yadj);
+        if (!pipplayer)
+        {
+            if (location == kPIPTopLeft || location == kPIPTopRight)
+                ypos = display_video_rect.y();
+            else
+                ypos = -(display_video_rect.y());
+        }
+        
+        letterAdj = video_aspect / letterboxed_video_aspect;
+
+    }
+   
+    // set height
+    tmph = (frame_height * db_pip_size) / 100;
+
+    float dispPixelAdj = video_dim.width() / video_dim.height();
+   
+    tmpw = (int)(tmph * letterAdj * dispPixelAdj);
+   
+//    VERBOSE(VB_IMPORTANT, QString("DELETE ME tmpw %1 tmph %2 letteradj %3 dispPixelAdj %4")
+//            .arg(tmpw).arg(tmph).arg(letterAdj).arg(dispPixelAdj));
+    switch (location)
+    {
+        default:
+        case kPIPTopLeft:
+            xpos = 30 + letterXadj;
+            ypos += 40 + letterYadj;
+            break;
+        case kPIPBottomLeft:
+            xpos = 30 + letterXadj;
+            ypos += frame_height - tmph - 40 - letterYadj;
+            break;
+        case kPIPTopRight:
+            xpos = frame_width  - tmpw - 30 - letterXadj;
+            ypos += 40 + letterXadj;
+            break;
+        case kPIPBottomRight:
+            xpos = frame_width  - tmpw - 30 - letterXadj;
+            ypos += frame_height - tmph - 40 - letterYadj; 
+            break;
+    }
+    return QRect(xpos, ypos, tmpw, tmph);
+}
+
 /**
  * \fn VideoOutput::DoPipResize(int,int)
  * \brief Sets up Picture in Picture image resampler.
@@ -1111,9 +1202,8 @@
     int pipw, piph;
 
     VideoFrame *pipimage = pipplayer->GetCurrentFrame(pipw, piph);
+
     float pipVideoAspect = pipplayer->GetVideoAspect();
-    uint  pipVideoWidth  = pipplayer->GetVideoWidth();
-    uint  pipVideoHeight = pipplayer->GetVideoHeight();
 
     // If PiP is not initialized to values we like, silently ignore the frame.
     if ((video_aspect <= 0) || (pipVideoAspect <= 0) || 
@@ -1123,40 +1213,13 @@
         pipplayer->ReleaseCurrentFrame(pipimage);
         return;
     }
+    
+    QRect piprect = GetPIPRect(db_pip_location, pipplayer);
 
-    // set height
-    int tmph = (frame->height * db_pip_size) / 100;
-    pip_desired_display_size.setHeight((tmph >> 1) << 1);
-
-    // adjust for letterbox modes...
-    int letterXadj = 0;
-    int letterYadj = 0;
-    float letterAdj = 1.0f;
-    if (letterbox != kLetterbox_Off)
-    {
-        letterXadj = max(-display_video_rect.left(), 0);
-        float xadj = (float) video_rect.width() / display_visible_rect.width();
-        letterXadj = (int) (letterXadj * xadj);
-
-        float yadj = (float)video_rect.height() /display_visible_rect.height();
-        letterYadj = max(-display_video_rect.top(), 0);
-        letterYadj = (int) (letterYadj * yadj);
-
-        letterAdj  = video_aspect / letterboxed_video_aspect;
-    }
-
-    // adjust for non-square pixels on screen
-    float dispPixelAdj = (GetDisplayAspect() * video_dim.height()) /
-        video_dim.width();
-
-    // adjust for non-square pixels in video
-    float vidPixelAdj  = pipVideoWidth / (pipVideoAspect * pipVideoHeight);
-
-    // set width
-    int tmpw = (int) (pip_desired_display_size.height() * pipVideoAspect *
-                      vidPixelAdj * dispPixelAdj * letterAdj);
-    pip_desired_display_size.setWidth((tmpw >> 1) << 1);
-
+    pip_desired_display_size.setWidth((piprect.width() >> 1 ) << 1);
+    pip_desired_display_size.setHeight((piprect.height() >> 1) << 1);
+   
+    
     // Scale the image if we have to...
     unsigned char *pipbuf = pipimage->buf;
     if (pipw != pip_desired_display_size.width() ||
@@ -1186,28 +1249,8 @@
 
 
     // Figure out where to put the Picture-in-Picture window
-    int xoff = 0;
-    int yoff = 0;
-    switch (db_pip_location)
-    {
-        default:
-        case kPIPTopLeft:
-                xoff = 30 + letterXadj;
-                yoff = 40 + letterYadj;
-                break;
-        case kPIPBottomLeft:
-                xoff = 30 + letterXadj;
-                yoff = frame->height - piph - 40 - letterYadj;
-                break;
-        case kPIPTopRight:
-                xoff = frame->width  - pipw - 30 - letterXadj;
-                yoff = 40 + letterYadj;
-                break;
-        case kPIPBottomRight:
-                xoff = frame->width  - pipw - 30 - letterXadj;
-                yoff = frame->height - piph - 40 - letterYadj;
-                break;
-    }
+    int xoff = piprect.x();
+    int yoff = piprect.y();
 
     // Copy Y (intensity values)
     for (int i = 0; i < piph; i++)
Index: libs/libmythtv/pipplayer.cpp
===================================================================
--- libs/libmythtv/pipplayer.cpp	(revision 0)
+++ libs/libmythtv/pipplayer.cpp	(revision 0)
@@ -0,0 +1,359 @@
+#include <math.h>
+#include "pipplayer.h"
+#include "remoteutil.h"
+
+#define LOC QString("PIPPlayer: ")
+#define LOC_ERR QString("PIPPlayer Error: ")
+
+static void *SpawnPIPVideoThread(void *param)
+{   
+    NuppelVideoPlayer *nvp = (NuppelVideoPlayer *)param;
+    nvp->StartPlaying();
+    nvp->StopPlaying();
+    return NULL;
+}
+ 
+PIPPlayer::PIPPlayer(void)
+    :   piprecorder(NULL), piprbuffer(NULL),
+        piptvchain(NULL), piprecinfo(NULL),
+        pipnvp(NULL), pipWindow(NULL),
+        islivetv(false), 
+        reinit(true), using_nullvideo(false)
+{
+};
+
+PIPPlayer::~PIPPlayer(void)
+{
+    StopPlaying();
+    if (pipWindow)
+        pipWindow->deleteLater();
+};
+
+PIPPlayer * PIPPlayer::Create(NuppelVideoPlayer *parentnvp, int location)
+{
+    PIPPlayer *tmppip = new PIPPlayer();
+    if (parentnvp)
+    {
+        QRect rect = parentnvp->getVideoOutput()->GetPIPRect(location);
+        tmppip->Init(rect, QString("pip player %1").arg((int)location));
+        return tmppip;
+    }
+    delete tmppip;
+    return NULL;
+}
+
+PIPPlayer * PIPPlayer::Create(const QRect &rect)
+{
+    PIPPlayer *tmppip = new PIPPlayer();
+    tmppip->Init(rect, "pip player");
+    return tmppip;
+}
+
+void PIPPlayer::Init(QRect rect, QString name)
+{
+    QRect piprect = QRect(rect);
+    MythDialog *window = new MythDialog(gContext->GetMainWindow(), name);
+    window->setNoErase();
+    window->setGeometry(piprect);
+    window->setFixedSize(piprect.size());
+    window->show();
+    window->setBackgroundColor(Qt::black);
+    gContext->GetMainWindow()->detach(window);
+    pipWindow = window;
+}
+
+void PIPPlayer::Reinitialize(void)
+{
+    if (pipnvp)
+        delete pipnvp;
+
+    pipnvp = NULL;
+    
+    if (piprbuffer)
+        delete piprbuffer;
+    piprbuffer = NULL;
+    
+    if (piprecinfo)
+        delete piprecinfo;
+    piprecinfo = NULL;
+    
+    if (piprecorder)
+        delete piprecorder;
+    piprecorder = NULL;
+    
+    if (piptvchain)
+    {
+        piptvchain->DestroyChain();
+        delete piptvchain;
+    }
+    piptvchain = NULL;
+}
+
+/*
+ * \brief Setup pip and start playing it.
+ * \param piptype: set to true, if pip should open a tuner
+ * \returns true if setup is complete
+ */
+bool PIPPlayer::StartPlaying(ProgramInfo *rec, bool piptype, bool nullvideo)
+{
+
+    using_nullvideo = nullvideo;
+    islivetv = piptype;
+  
+    if (reinit)
+        Reinitialize();
+
+    RemoteEncoder *testrec = NULL;
+    
+    VERBOSE(VB_PLAYBACK, LOC + 
+            QString("PIP is for %1").arg((islivetv) ? "live tv":"a recording"));
+
+    if (islivetv)
+    {
+        if (!(piprecorder && piprbuffer && piptvchain))
+        {
+            testrec = RemoteRequestRecorder();
+
+            if (!testrec || !testrec->IsValidRecorder())
+            {
+                VERBOSE(VB_IMPORTANT, LOC_ERR + "PIP failed to locate recorder");
+                if (testrec)
+                    delete testrec;
+                return false;
+            }
+
+            testrec->Setup();
+
+            piptvchain = new LiveTVChain();
+            piptvchain->InitializeNewChain("PIP"+gContext->GetHostName());
+            testrec->SpawnLiveTV(piptvchain->GetID(), true);
+            piptvchain->ReloadAll();
+            piprecinfo = piptvchain->GetProgramAt(-1);
+            if (!piprecinfo)
+            {
+                VERBOSE(VB_IMPORTANT, LOC_ERR + 
+                        "PIP cannot find live tv programinfo. Exiting");
+                delete testrec;
+                piptvchain->DestroyChain();
+                delete piptvchain;
+                return false;
+            }
+            else
+            {
+                QString playbackURL = piprecinfo->GetPlaybackURL();
+                piptvchain->SetProgram(piprecinfo);
+                piprbuffer = new RingBuffer(playbackURL, false);
+                piprbuffer->SetLiveMode(piptvchain);
+            }
+
+            piprecorder = testrec;
+        
+            if (!StartRecorder(piprecorder, -1))
+            {
+                VERBOSE(VB_IMPORTANT, LOC_ERR + "PIP recorder failed to start");
+                return false;
+            }
+        }
+    }
+    else // pip is not Live TV
+    {
+        if (!piprecinfo)
+            piprecinfo = new ProgramInfo(*rec);
+        if (!piprbuffer)
+            piprbuffer = new RingBuffer(piprecinfo->pathname, false, false, 1);
+        if (!piprbuffer->IsOpen())
+        {
+            VERBOSE(VB_IMPORTANT, LOC_ERR + 
+                QString("Failed to open Ringbuffer %1")
+                .arg(piprecinfo->pathname));
+            return false;
+        }
+    }
+
+    // when starting pipplayer for the first time, always start
+    // from the beginning
+    if (reinit && piprecinfo)
+        piprecinfo->setIgnoreBookmark(true);
+        
+    pipnvp = new NuppelVideoPlayer("pip player", piprecinfo);
+    pipnvp->SetParentWidget(pipWindow);
+    pipnvp->SetRingBuffer(piprbuffer);
+    if (islivetv)
+    {
+        pipnvp->SetRecorder(piprecorder);
+        pipnvp->SetLiveTVChain(piptvchain);
+    }
+    else
+        pipnvp->SetLength(piprecinfo->CalculateLength());
+        
+
+    // setAsPIP is true if null video output is used
+    // PIP will be embedded in XV
+    if (using_nullvideo)
+    {
+        pipnvp->SetAsPIP(true);
+    }
+    else
+        pipnvp->SetAsPIP(false);
+
+    VERBOSE(VB_PLAYBACK, "PIP Waiting for NVP");
+    pthread_create(&pipdecode, NULL, SpawnPIPVideoThread, pipnvp);
+    int maxWait = 20000;
+    MythTimer t;
+    t.start();
+    while (!pipnvp->IsPlaying() && pipnvp->IsDecoderThreadAlive() &&
+            t.elapsed() < maxWait)
+    {
+        usleep(5000);
+    }
+    
+    if (!pipnvp->IsPlaying())
+    {
+        VERBOSE(VB_PLAYBACK, LOC_ERR + "PIP NVP Failed to Start");
+        return false;
+    }
+    
+    VERBOSE(VB_PLAYBACK, LOC + "PIP NVP Started");
+    return true;
+} 
+
+void PIPPlayer::StopPlaying(void)
+{
+    
+    if (!pipnvp)
+        return;
+
+    if (pipnvp->IsPlaying())
+    {
+        if (reinit)
+            piprbuffer->StopReads();
+        piprbuffer->Pause();
+        piprbuffer->WaitForPause();
+        pipnvp->StopPlaying();
+    }
+    
+    VERBOSE(VB_PLAYBACK, LOC + "KillPlayer(): Stopped Playing");
+    {
+        pthread_join(pipdecode, NULL);
+        delete pipnvp;
+        pipnvp = NULL;
+    }
+
+    if (reinit)
+    {
+        if (islivetv && piprecorder ) 
+            piprecorder->StopLiveTV();
+    
+        Reinitialize();
+    }
+    
+    VERBOSE(VB_PLAYBACK, LOC + "KillPlayer(): NVP deleted");
+}
+
+/*
+ * \brief set pip ringbuffer if pip is not playing
+ */
+void PIPPlayer::SetRingBuffer(RingBuffer *rbuffer)
+{
+    if (!IsPlaying())
+        piprbuffer = rbuffer;
+}
+
+/*
+ * \brief set pip tvchain if pip is not playing
+ */
+void PIPPlayer::SetLiveTVChain(LiveTVChain *tvchain)
+{
+    if (!IsPlaying())
+        piptvchain = tvchain;
+}
+
+/*
+ * \brief set pip recorder if pip is not playing
+ */
+void PIPPlayer::SetRecorder(RemoteEncoder  *recorder)
+{
+    if (!IsPlaying())
+        piprecorder = recorder;
+}
+
+void PIPPlayer::SetProgramInfo(ProgramInfo *pginfo)
+{
+    if (!IsPlaying())
+    {
+        if (piprecinfo)
+            delete piprecinfo;
+        piprecinfo = pginfo;
+    }
+}
+
+void PIPPlayer::SetFrameRate(double fps)
+{
+    if (!pipnvp || pipnvp->GetFrameRate() == fps)
+        return;
+
+    pipnvp->SetVideoParams(pipnvp->GetVideoWidth(),
+                            pipnvp->GetVideoHeight(),
+                            fps, 15);
+}
+
+bool PIPPlayer::IsSameProgram(ProgramInfo *rec)
+{
+    if (!rec || !piprecinfo)
+        return false;
+
+    if (piprecinfo->IsSameProgram(*rec))
+        return true;
+    
+    return false;
+}
+
+bool PIPPlayer::StartRecorder(RemoteEncoder *rec, int maxWait)
+{
+    maxWait = (maxWait <= 0) ? 40000 : maxWait;
+    MythTimer t;
+    t.start();
+    while (rec && !rec->IsRecording() && t.elapsed() < maxWait)
+        usleep(5000);
+    if (rec && !rec->IsRecording())
+    {
+        VERBOSE(VB_IMPORTANT, LOC_ERR + "recorder startup failed. Timed out");
+        return false;
+    }
+    return true;
+}
+
+void PIPPlayer::Hide(void)
+{
+    if (pipWindow && pipWindow->isVisible())
+        pipWindow->hide();
+}
+
+void PIPPlayer::Show(void)
+{   
+    if (pipWindow && pipWindow->isHidden())
+        pipWindow->show();
+}
+
+bool PIPPlayer::IsHidden(void)
+{
+    if (pipWindow && pipWindow->isHidden())
+        return true;
+    return false;
+}
+
+void PIPPlayer::DisplaySoftwareScaledImage(void)
+{
+    if (!using_nullvideo)
+        return;
+   
+    QPainter p(pipWindow);
+    QSize size = pipWindow->size();
+    float saspect = ((float)size.width())/ ((float)size.height());
+    float vaspect = pipnvp->GetVideoAspect();
+    size.setHeight((int) ceil(size.height() * (saspect / vaspect)));
+    size.setHeight(((size.height() + 7) / 8) * 8);
+    size.setWidth( ((size.width()  + 7) / 8) * 8);
+    const QImage &img = pipnvp->GetARGBFrame(size);
+    p.drawImage(0, 0, img); 
+}
Index: libs/libmythtv/videoout_xv.h
===================================================================
--- libs/libmythtv/videoout_xv.h	(revision 11680)
+++ libs/libmythtv/videoout_xv.h	(working copy)
@@ -88,6 +88,8 @@
         { return XVideoIDCT <= VideoOutputSubType(); }
     virtual bool hasVLDAcceleration(void) const
         { return XVideoVLD == VideoOutputSubType(); }
+    virtual bool hasXVAcceleration(void) const
+        { return VideoOutputSubType() >= XVideo; }
 
     void CheckFrameStates(void);
 
Index: libs/libmythtv/videoout_xv.cpp
===================================================================
--- libs/libmythtv/videoout_xv.cpp	(revision 11680)
+++ libs/libmythtv/videoout_xv.cpp	(working copy)
@@ -1218,8 +1218,17 @@
         db_vdisp_profile->SetVideoRenderer(renderer);
     }
 
+    const QString osdrenderer = db_vdisp_profile->GetOSDRenderer();
+    if (piptype == kPIPOnTV  &&
+            (osdrenderer != "opengl" || osdrenderer != "composite"))
+    {
+        VERBOSE(VB_IMPORTANT, LOC + QString("XV PIP not supported with blended OSD. "
+                    "Using software scaled PIP."));
+        return false;
+    }
     // Initialize the OSD, if we need to
-    InitOSD(db_vdisp_profile->GetOSDRenderer());
+    if (piptype == kPIPOff)
+        InitOSD(osdrenderer);
 
     // Create video buffers
     bool use_xv  = (renderer.left(2) == "xv");
@@ -1259,6 +1268,11 @@
 {
     needrepaint = true;
 
+    // for PIP use software scaled image if width or height <= 64
+    if (piptype > kPIPOff &&
+        (width <= 64 || height <= 64))
+        return false;
+        
     XV_INIT_FATAL_ERROR_TEST(winid <= 0, "Invalid Window ID.");
 
     XJ_disp = MythXOpenDisplay();
Index: libs/libmythtv/videooutbase.h
===================================================================
--- libs/libmythtv/videooutbase.h	(revision 11680)
+++ libs/libmythtv/videooutbase.h	(working copy)
@@ -79,6 +79,13 @@
     kPIPBottomRight
 };
 
+enum PIPType
+{
+    kPIPOff = 0,
+    kPIPOn, // PIP but not for TV
+    kPIPOnTV // PIP used in TV mode
+};
+
 enum ZoomDirections
 {
     kZoomHome = 0,
@@ -225,12 +232,14 @@
     bool AllowPreviewEPG(void) { return allowpreviewepg; }
 
     /// \brief Returns true iff Motion Compensation acceleration is available.
-    virtual bool hasMCAcceleration() const { return false; }
+    virtual bool hasMCAcceleration(void) const { return false; }
     /// \brief Returns true iff Inverse Discrete Cosine Transform acceleration
     ///        is available.
-    virtual bool hasIDCTAcceleration() const { return false; }
+    virtual bool hasIDCTAcceleration(void) const { return false; }
     /// \brief Returns true iff VLD acceleration is available.
-    virtual bool hasVLDAcceleration() const { return false; }
+    virtual bool hasVLDAcceleration(void) const { return false; }
+    /// \brief Returns true if XV or XVMC is available
+    virtual bool hasXVAcceleration(void) const { return false; }
 
     /// \brief Sets the number of frames played
     virtual void SetFramesPlayed(long long fp) { framesPlayed = fp; };
@@ -308,6 +317,13 @@
     /// \brief Tells the player to resize the video frame (used for ITV)
     void SetVideoResize(const QRect &videoRect);
 
+    /// \brief returns QRect of PIP based on PIPLocation
+    QRect GetPIPRect(int location, NuppelVideoPlayer *pipplayer = NULL);
+
+    /// set PIP Type
+    void SetAsPIP(PIPType setting) { piptype = setting; }
+        
+
   protected:
     void InitBuffers(int numdecode, bool extra_for_pause, int need_free,
                      int needprebuffer_normal, int needprebuffer_small,
@@ -384,6 +400,7 @@
     QSize   pip_video_size;
     unsigned char      *pip_tmp_buf;
     ImgReSampleContext *pip_scaling_context;
+    PIPType    piptype;
 
     // Video resizing (for ITV)
     bool    vsz_enabled;
Index: programs/mythfrontend/playbackbox.cpp
===================================================================
--- programs/mythfrontend/playbackbox.cpp	(revision 11680)
+++ programs/mythfrontend/playbackbox.cpp	(working copy)
@@ -38,6 +38,7 @@
 #include "remoteutil.h"
 #include "lcddevice.h"
 #include "previewgenerator.h"
+#include "pipplayer.h"
 #include "playgroup.h"
 #include "customedit.h"
 
@@ -262,12 +263,10 @@
       // Volatile drawing variables
       paintSkipCount(0),                paintSkipUpdate(false),
       // Preview Video Variables
-      previewVideoNVP(NULL),            previewVideoRingBuf(NULL),
-      previewVideoRefreshTimer(new QTimer(this)),
-      previewVideoBrokenRecId(0),       previewVideoState(kStopped),
-      previewVideoStartTimerOn(false),  previewVideoEnabled(false),
-      previewVideoPlaying(false),       previewVideoThreadRunning(false),
-      previewVideoKillState(kDone),
+      previewPlayer(NULL), previewVideoStartTimer(new QTimer(this)),
+      previewVideoRefreshTimer(new QTimer(this)), 
+      previewVideoEnabled(false),
+      previewTimeout(2000), software_scaled(false),
       // Preview Image Variables
       previewPixmapEnabled(false),      previewPixmap(NULL),
       previewSuspend(false),            previewChanid(""),
@@ -369,17 +368,19 @@
     connected = FillList();
 
     // connect up timers...
-    connect(previewVideoRefreshTimer, SIGNAL(timeout()),
+    connect(previewVideoStartTimer,        SIGNAL(timeout()),
             this,                     SLOT(timeout()));
+    connect(previewVideoRefreshTimer,       SIGNAL(timeout()),
+            this,                     SLOT(refreshVideo()));
     connect(freeSpaceTimer,           SIGNAL(timeout()),
             this,                     SLOT(setUpdateFreeSpace()));
     connect(fillListTimer,            SIGNAL(timeout()),
             this,                     SLOT(listChanged()));
 
     // preview video & preview pixmap init
-    previewVideoRefreshTimer->start(500);
     previewStartts = QDateTime::currentDateTime();
-
+    previewVideoStartTimer->start(previewTimeout);
+    previewVideoRefreshTimer->start(50);
     // misc setup
     updateBackground();
     setNoErase();
@@ -398,8 +399,14 @@
     gContext->removeListener(this);
     gContext->removeCurrentLocation();
 
-    if (!m_player)
-        killPlayerSafe();
+    killPlayer();
+    
+    if (previewVideoStartTimer)
+    {
+        previewVideoStartTimer->disconnect(this);
+        previewVideoStartTimer->deleteLater();
+        previewVideoStartTimer = NULL;
+    }
 
     if (previewVideoRefreshTimer)
     {
@@ -407,7 +414,7 @@
         previewVideoRefreshTimer->deleteLater();
         previewVideoRefreshTimer = NULL;
     }
-
+        
     if (fillListTimer)
     {
         fillListTimer->disconnect(this);
@@ -464,35 +471,7 @@
         delete previewPixmap;
         previewPixmap = NULL;
     }
-}
 
-/* blocks until playing has stopped */
-void PlaybackBox::killPlayerSafe(void)
-{
-    QMutexLocker locker(&previewVideoKillLock);
-
-    // Don't process any keys while we are trying to make the nvp stop.
-    // Qt's setEnabled(false) doesn't work, because of LIRC events...
-    ignoreKeyPressEvents = true;
-
-    while (previewVideoState != kKilled && previewVideoState != kStopped &&
-           previewVideoThreadRunning)
-    {
-        /* ensure that key events don't mess up our previewVideoStates */
-        previewVideoState = (previewVideoState == kKilled) ?
-            kKilled :  kKilling;
-
-        /* NOTE: need unlock/process/lock here because we need
-           to allow updateVideo() to run to handle changes in
-           previewVideoStates */
-        qApp->unlock();
-        qApp->processEvents();
-        usleep(500);
-        qApp->lock();
-    }
-    previewVideoState = kStopped;
-
-    ignoreKeyPressEvents = false;
 }
 
 void PlaybackBox::LoadWindow(QDomElement &element)
@@ -523,6 +502,14 @@
             }
         }
     }
+
+    if (previewVideoEnabled)
+    {
+        previewPlayer = PIPPlayer::Create(drawVideoBounds);
+        if (previewPlayer)
+            previewPlayer->Hide();
+        previewPixmapEnabled = true;
+    }
 }
 
 void PlaybackBox::parseContainer(QDomElement &element)
@@ -546,7 +533,7 @@
         drawUsageBounds = area;
     if (name.lower() == "cur_group")
         drawCurGroupBounds = area;        
-    
+   
 }
 
 void PlaybackBox::parsePopup(QDomElement &element)
@@ -596,6 +583,7 @@
 
 void PlaybackBox::exitWin()
 {
+    killPlayer();
     if (m_player)
     {
         if (curitem)
@@ -603,9 +591,6 @@
         curitem = NULL;
         pbbIsVisibleCond.wakeAll();
     }
-    else
-        killPlayerSafe();
-
     accept();
 }
 
@@ -785,8 +770,6 @@
     QMap<QString, QString> infoMap;
     QPainter tmp(&pix);
         
-    if (previewVideoPlaying)
-        previewVideoState = kChanging;
 
     LayerSet *container = NULL;
     if (type != Delete)
@@ -799,8 +782,7 @@
         if (curitem)
             curitem->ToMap(infoMap);
         
-        if ((previewVideoEnabled == 0) &&
-            (previewPixmapEnabled == 0))
+        if (previewPixmapEnabled == 0)
             container->UseAlternateArea(true);
 
         container->ClearAllText();
@@ -845,8 +827,6 @@
     tmp.end();
     p->drawPixmap(pr.topLeft(), pix);
 
-    previewVideoStartTimer.start();
-    previewVideoStartTimerOn = true;
 }
 
 void PlaybackBox::updateInfo(QPainter *p)
@@ -883,130 +863,27 @@
     // If we're displaying group info don't update the video.
     if (inTitle && haveGroupInfoSet)
         return;
-
+    
     /* show a still frame if the user doesn't want a video preview or nvp 
      * hasn't started playing the video preview yet */
-    if (curitem && !playingSomething &&
-        (!previewVideoEnabled             ||
-         !previewVideoPlaying             ||
-         (previewVideoState == kStarting) || 
-         (previewVideoState == kChanging)))
+    if ((curitem && previewPixmapEnabled && !previewPlayer) ||
+         (curitem && previewPlayer && previewPlayer->IsHidden()))
     {
         QPixmap temp = getPixmap(curitem);
         if (temp.width() > 0)
             p->drawPixmap(drawVideoBounds.x(), drawVideoBounds.y(), temp);
     }
-
-    /* keep calling killPlayer() to handle nvp cleanup */
-    /* until killPlayer() is done */
-    if (previewVideoKillState != kDone && !killPlayer())
-        return;
-
-    /* if we aren't supposed to have a preview playing then always go */
-    /* to the stopping previewVideoState */
-    if (!previewVideoEnabled &&
-        (previewVideoState != kKilling) && (previewVideoState != kKilled))
+    
+    if (curitem && previewVideoEnabled && previewPlayer && 
+            !previewPlayer->IsHidden())
     {
-        previewVideoState = kStopping;
-    }
-
-    /* if we have no nvp and aren't playing yet */
-    /* if we have an item we should start playing */
-    if (!previewVideoNVP   && previewVideoEnabled  &&
-        curitem            && !previewVideoPlaying &&
-        (previewVideoState != kKilling) &&
-        (previewVideoState != kKilled)  &&
-        (previewVideoState != kStarting))
-    {
-        ProgramInfo *rec = curitem;
-
-        if (fileExists(rec) == false)
-        {
-            VERBOSE(VB_IMPORTANT, QString("Error: File '%1' missing.")
-                    .arg(rec->pathname));
-
-            previewVideoState = kStopping;
-
-            ProgramInfo *tmpItem = findMatchingProg(rec);
-            if (tmpItem)
-                tmpItem->availableStatus = asFileNotFound;
-
-            return;
-        }
-        previewVideoState = kStarting;
-    }
-
-    if (previewVideoState == kChanging)
-    {
-        if (previewVideoNVP)
-        {
-            killPlayer(); /* start killing the player */
-            return;
-        }
-
-        previewVideoState = kStarting;
-    }
-
-    if ((previewVideoState == kStarting) && 
-        (!previewVideoStartTimerOn ||
-         (previewVideoStartTimer.elapsed() > 500)))
-    {
-        previewVideoStartTimerOn = false;
-
-        if (!previewVideoNVP)
-            startPlayer(curitem);
-
-        if (previewVideoNVP)
-        {
-            if (previewVideoNVP->IsPlaying())
-                previewVideoState = kPlaying;
-        }
+        if (!previewPlayer->IsSameProgram(curitem))
+            stopPlayer();
         else
-        {
-            // already dead, so clean up
-            killPlayer();
-            return;
-        }
+            previewPlayer->GetNVP()->ExposeEvent();
     }
-
-    if ((previewVideoState == kStopping) || (previewVideoState == kKilling))
-    {
-        if (previewVideoNVP)
-        {
-            killPlayer(); /* start killing the player and exit */
-            return;
-        }
-
-        if (previewVideoState == kKilling)
-            previewVideoState = kKilled;
-        else
-            previewVideoState = kStopped;
-    }
-
-    /* if we are playing and nvp is running, then grab a new video frame */
-    if ((previewVideoState == kPlaying) && previewVideoNVP->IsPlaying() &&
-        !playingSomething)
-    {
-        QSize size = drawVideoBounds.size();
-        float saspect = ((float)size.width()) / ((float)size.height());
-        float vaspect = previewVideoNVP->GetVideoAspect();
-        size.setHeight((int) ceil(size.height() * (saspect / vaspect)));
-        size.setHeight(((size.height() + 7) / 8) * 8);
-        size.setWidth( ((size.width()  + 7) / 8) * 8);
-        const QImage &img = previewVideoNVP->GetARGBFrame(size);
-        p->drawImage(drawVideoBounds.x(), drawVideoBounds.y(), img);
-    }
-
-    /* have we timed out waiting for nvp to start? */
-    if ((previewVideoState == kPlaying) && !previewVideoNVP->IsPlaying())
-    {
-        if (previewVideoPlayingTimer.elapsed() > 2000)
-        {
-            previewVideoState = kStarting;
-            killPlayer();
-            return;
-        }
-    }
+   
+    previewVideoStartTimer->changeInterval(previewTimeout);
 }
 
 void PlaybackBox::updateUsage(QPainter *p)
@@ -1360,7 +1237,7 @@
     if (!inTitle)
     {
         if (haveGroupInfoSet)
-            killPlayerSafe();
+            killPlayer();
         
         inTitle = true;
         paintSkipUpdate = false;
@@ -1964,127 +1841,48 @@
     return (progCache != NULL);
 }
 
-static void *SpawnPreviewVideoThread(void *param)
+void PlaybackBox::killPlayer(void)
 {
-    NuppelVideoPlayer *nvp = (NuppelVideoPlayer *)param;
-    nvp->StartPlaying();
-    return NULL;
-}
-
-bool PlaybackBox::killPlayer(void)
-{
-    QMutexLocker locker(&previewVideoUnsafeKillLock);
-
-    previewVideoPlaying = false;
-
-    /* if we don't have nvp to deal with then we are done */
-    if (!previewVideoNVP)
+    if (previewPlayer)
     {
-        previewVideoKillState = kDone;
-        return true;
+        stopPlayer();
+        delete previewPlayer;
+        previewPlayer = NULL;
     }
-
-    if (previewVideoKillState == kDone)
-    {
-        previewVideoKillState = kNvpToPlay;
-        previewVideoKillTimeout.start();
-    }
- 
-    if (previewVideoKillState == kNvpToPlay)
-    {
-        if (previewVideoNVP->IsPlaying() ||
-            (previewVideoKillTimeout.elapsed() > 2000))
-        {
-            previewVideoKillState = kNvpToStop;
-
-            previewVideoRingBuf->Pause();
-            previewVideoNVP->StopPlaying();
-        }
-        else /* return false status since we aren't done yet */
-            return false;
-    }
-
-    if (previewVideoKillState == kNvpToStop)
-    {
-        if (!previewVideoNVP->IsPlaying() ||
-            (previewVideoKillTimeout.elapsed() > 2000))
-        {
-            pthread_join(previewVideoThread, NULL);
-            previewVideoThreadRunning = true;
-            delete previewVideoNVP;
-            delete previewVideoRingBuf;
-
-            previewVideoNVP = NULL;
-            previewVideoRingBuf = NULL;
-            previewVideoKillState = kDone;
-        }
-        else /* return false status since we aren't done yet */
-            return false;
-    }
-
-    return true;
 }        
 
 void PlaybackBox::startPlayer(ProgramInfo *rec)
 {
-    previewVideoPlaying = true;
-
-    if (rec != NULL)
+    ignoreKeyPressEvents = true; 
+    QMutexLocker locker(&previewVideoLock);
+    if (rec != NULL && previewPlayer)
     {
-        // Don't keep trying to open broken files when just sitting on entry
-        if (previewVideoBrokenRecId &&
-            previewVideoBrokenRecId == rec->recordid)
+        previewPlayer->Show();
+        if (!software_scaled)
+            previewPlayer->StartPlaying(rec, false);
+        if (!previewPlayer->IsPlaying())
         {
-            return;
+            software_scaled = true;
+            previewPlayer->StartPlaying(rec, false, true);
         }
+    }
+    ignoreKeyPressEvents = false;
+}
 
-        if (previewVideoRingBuf || previewVideoNVP)
-        {
-            VERBOSE(VB_IMPORTANT,
-                    "PlaybackBox::startPlayer(): Error, last preview window "
-                    "didn't clean up. Not starting a new preview.");
-            return;
-        }
-
-        previewVideoRingBuf = new RingBuffer(rec->pathname, false, false, 1);
-        if (!previewVideoRingBuf->IsOpen())
-        {
-            VERBOSE(VB_IMPORTANT, LOC_ERR +
-                    "Could not open file for preview video.");
-            delete previewVideoRingBuf;
-            previewVideoRingBuf = NULL;
-            previewVideoBrokenRecId = rec->recordid;
-            return;
-        }
-        previewVideoBrokenRecId = 0;
-
-        previewVideoNVP = new NuppelVideoPlayer("preview player");
-        previewVideoNVP->SetRingBuffer(previewVideoRingBuf);
-        previewVideoNVP->SetAsPIP();
-        QString filters = "";
-        previewVideoNVP->SetVideoFilters(filters);
-
-        previewVideoThreadRunning = true;
-        pthread_create(&previewVideoThread, NULL,
-                       SpawnPreviewVideoThread, previewVideoNVP);
-
-        previewVideoPlayingTimer.start();
-
-        previewVideoState = kStarting;
-
-        int previewRate = 30;
-        if (gContext->GetNumSetting("PlaybackPreviewLowCPU", 0))
-        {
-            previewRate = 12;
-        }
-        
-        previewVideoRefreshTimer->start(1000 / previewRate); 
+void PlaybackBox::stopPlayer(void)
+{
+    ignoreKeyPressEvents = true;
+    QMutexLocker locker(&previewVideoLock);
+    if (previewPlayer)
+    {
+        previewPlayer->StopPlaying();
+        previewPlayer->Hide();
     }
+    ignoreKeyPressEvents = false;
 }
 
 void PlaybackBox::playSelectedPlaylist(bool random)
 {
-    previewVideoState = kStopping;
 
     if (!curitem)
         return;
@@ -2115,7 +1913,6 @@
 
 void PlaybackBox::playSelected()
 {
-    previewVideoState = kStopping;
 
     if (!curitem)
         return;
@@ -2137,7 +1934,6 @@
 
 void PlaybackBox::stopSelected()
 {
-    previewVideoState = kStopping;
 
     if (!curitem)
         return;
@@ -2147,7 +1943,6 @@
 
 void PlaybackBox::deleteSelected()
 {
-    previewVideoState = kStopping;
 
     if (!curitem)
         return;
@@ -2161,7 +1956,6 @@
 
 void PlaybackBox::upcoming()
 {
-    previewVideoState = kStopping;
 
     if (!curitem)
         return;
@@ -2180,7 +1974,6 @@
 
 void PlaybackBox::customEdit()
 {
-    previewVideoState = kStopping;
 
     if (!curitem)
         return;
@@ -2203,7 +1996,6 @@
 
 void PlaybackBox::details()
 {
-    previewVideoState = kStopping;
 
     if (!curitem)
         return;
@@ -2216,7 +2008,6 @@
 
 void PlaybackBox::selected()
 {
-    previewVideoState = kStopping;
 
     if (inTitle && haveGroupInfoSet)
     {
@@ -2236,7 +2027,7 @@
 
 void PlaybackBox::showMenu()
 {
-    killPlayerSafe();
+    stopPlayer();
 
     popup = new MythPopupBox(gContext->GetMainWindow(), drawPopupSolid,
                              drawPopupFgColor, drawPopupBgColor,
@@ -2299,6 +2090,8 @@
 
 bool PlaybackBox::play(ProgramInfo *rec, bool inPlaylist)
 {
+    killPlayer(); 
+
     bool playCompleted = false;
 
     if (!rec)
@@ -2327,7 +2120,6 @@
     ProgramInfo *tvrec = new ProgramInfo(*rec);
 
     setEnabled(false);
-    previewVideoState = kKilling; // stop preview playback and don't restart it
     playingSomething = true;
 
     playCompleted = TV::StartTV(tvrec, false, inPlaylist, underNetworkControl);
@@ -2335,13 +2127,17 @@
     playingSomething = false;
     setEnabled(true);
 
-
-    previewVideoState = kStarting; // restart playback preview
-
     delete tvrec;
 
     connected = FillList();
 
+    if (previewVideoEnabled && !previewPlayer)
+    {
+        previewPlayer = PIPPlayer::Create(drawVideoBounds);
+        if (previewPlayer)
+            previewPlayer->Hide();
+    }
+
     return playCompleted;
 }
 
@@ -2353,8 +2149,7 @@
 bool PlaybackBox::doRemove(ProgramInfo *rec, bool forgetHistory,
                            bool forceMetadataDelete)
 {
-    previewVideoBrokenRecId = rec->recordid;
-    killPlayerSafe();
+    stopPlayer();
 
     if (playList.grep(rec->MakeUniqueKey()).count())
         togglePlayListItem(rec);
@@ -2367,7 +2162,6 @@
 
 void PlaybackBox::remove(ProgramInfo *toDel)
 {
-    previewVideoState = kStopping;
 
     if (delitem)
         delete delitem;
@@ -2378,7 +2172,7 @@
 
 void PlaybackBox::showActions(ProgramInfo *toExp)
 {
-    killPlayer();
+    stopPlayer();
 
     if (delitem)
         delete delitem;
@@ -3041,7 +2835,7 @@
 void PlaybackBox::initPopup(MythPopupBox *popup, ProgramInfo *program,
                             QString message, QString message2)
 {
-    killPlayerSafe();
+    stopPlayer();
 
     QDateTime recstartts = program->recstartts;
     QDateTime recendts = program->recendts;
@@ -3150,9 +2944,7 @@
 
     cancelPopup();
 
-    previewVideoState = kChanging;
 
-    previewVideoRefreshTimer->start(500);
 }
 
 void PlaybackBox::doStop(void)
@@ -3164,9 +2956,7 @@
 
     stop(delitem);
 
-    previewVideoState = kChanging;
 
-    previewVideoRefreshTimer->start(500);
 }
 
 void PlaybackBox::showProgramDetails()
@@ -3316,9 +3106,7 @@
 
     cancelPopup();
 
-    previewVideoState = kChanging;
 
-    previewVideoRefreshTimer->start(500);
 }
 
 void PlaybackBox::doPlaylistDelete(void)
@@ -3362,9 +3150,7 @@
 
     bool result = doRemove(delitem, false, false);
 
-    previewVideoState = kChanging;
 
-    previewVideoRefreshTimer->start(500);
 
     if (result)
     {
@@ -3397,9 +3183,7 @@
 
     doRemove(delitem, true, true);
 
-    previewVideoState = kChanging;
 
-    previewVideoRefreshTimer->start(500);
 }
 
 void PlaybackBox::doDeleteForgetHistory(void)
@@ -3422,9 +3206,7 @@
 
     bool result = doRemove(delitem, true, false);
 
-    previewVideoState = kChanging;
 
-    previewVideoRefreshTimer->start(500);
 
     if (result)
     {
@@ -3499,8 +3281,6 @@
     delete delitem;
     delitem = NULL;
 
-    previewVideoState = kChanging;
-
     connected = FillList();      
     update(drawListBounds);
 }
@@ -3521,7 +3301,6 @@
     delete delitem;
     delitem = NULL;
 
-    previewVideoState = kChanging;
 
     connected = FillList();      
     update(drawListBounds);
@@ -3570,7 +3349,6 @@
 
     cancelPopup();
 
-    previewVideoState = kChanging;
 }
 
 void PlaybackBox::toggleView(ViewMask itemMask, bool setOn)
@@ -3590,8 +3368,6 @@
     if (!rec)
         return;
 
-    previewVideoState = kStopping;
-
     if (!rec)
         return;
 
@@ -3688,13 +3464,41 @@
     update(drawListBounds);
 }
 
+void PlaybackBox::refreshVideo(void)
+{
+    if (previewPlayer &&
+        previewPlayer->IsPlaying() &&
+        previewPlayer->UsingNullVideo())
+    {
+        QMutexLocker locker(&previewVideoLock);
+        previewPlayer->DisplaySoftwareScaledImage();
+    }
+}
+
 void PlaybackBox::timeout(void)
 {
     if (titleList.count() <= 1)
         return;
 
-    if (previewVideoEnabled)
-        update(drawVideoBounds);
+    if (previewPlayer)
+    {
+        int framerate;
+
+        if (expectingPopup ||
+            !(this == gContext->GetMainWindow()->currentWidget()))
+        {
+            return;
+        }
+        else if (previewPlayer->GetNVP() == NULL)
+            startPlayer(curitem);
+        else if (!previewPlayer->IsPlaying())
+            stopPlayer();
+        else
+        {
+            framerate = 10;
+            previewPlayer->SetFrameRate((float)framerate);
+        }
+    }       
 }
 
 void PlaybackBox::processNetworkControlCommands(void)
@@ -4286,8 +4090,6 @@
         return;
     }
 
-    killPlayerSafe();
-
     iconhelp->addLayout(grid);
 
     QButton *button = iconhelp->addButton(tr("Ok"));
@@ -4297,7 +4099,6 @@
 
     delete iconhelp;
 
-    previewVideoState = kChanging;
 
     paintSkipUpdate = false;
     paintSkipCount = 2;
@@ -4317,7 +4118,7 @@
     QLabel *label = recGroupPopup->addLabel(title, MythPopupBox::Large, false);
     label->setAlignment(Qt::AlignCenter);
 
-    killPlayerSafe();
+    stopPlayer();
 
 }
 
@@ -4342,8 +4143,6 @@
     paintSkipUpdate = false;
     paintSkipCount = 2;
 
-    previewVideoState = kChanging;
-
     setActiveWindow();
 
     if (delitem)
Index: programs/mythfrontend/globalsettings.cpp
===================================================================
--- programs/mythfrontend/globalsettings.cpp	(revision 11680)
+++ programs/mythfrontend/globalsettings.cpp	(working copy)
@@ -1839,16 +1839,6 @@
     return gc;
 }
 
-static HostCheckBox *PlaybackPreviewLowCPU()
-{
-    HostCheckBox *gc = new HostCheckBox("PlaybackPreviewLowCPU");
-    gc->setLabel(QObject::tr("CPU friendly preview of recordings"));
-    gc->setValue(false);
-    gc->setHelpText(QObject::tr("When enabled, recording previews "
-                    "will play with reduced FPS to save CPU."));
-    return gc;
-}
-
 static HostCheckBox *PlayBoxTransparency()
 {
     HostCheckBox *gc = new HostCheckBox("PlayBoxTransparency");
@@ -4187,7 +4177,6 @@
     pbox->addChild(PreviewPixmapOffset());
     pbox->addChild(PreviewFromBookmark());
     pbox->addChild(PlaybackPreview());
-    pbox->addChild(PlaybackPreviewLowCPU());
     pbox->addChild(PBBStartInTitle());
     pbox->addChild(PBBShowGroupSummary());
     addChild(pbox);
Index: programs/mythfrontend/playbackbox.h
===================================================================
--- programs/mythfrontend/playbackbox.h	(revision 11680)
+++ programs/mythfrontend/playbackbox.h	(working copy)
@@ -26,6 +26,7 @@
 class QTimer;
 class ProgramInfo;
 class PreviewGenerator;
+class PIPPlayer;
 
 class LayerSet;
 
@@ -108,6 +109,7 @@
     
   protected slots:
     void timeout(void);
+    void refreshVideo(void);
 
     void cursorLeft();
     void cursorRight();
@@ -267,9 +269,9 @@
     ProgramInfo *findMatchingProg(QString key);
     ProgramInfo *findMatchingProg(QString chanid, QString recstartts);
 
-    bool killPlayer(void);
-    void killPlayerSafe(void);
+    void killPlayer(void);
     void startPlayer(ProgramInfo *rec);
+    void stopPlayer(void);
 
     bool doRemove(ProgramInfo *, bool forgetHistory, bool forceMetadataDelete);
     void promptEndOfRecording(ProgramInfo *);
@@ -420,23 +422,14 @@
     QPixmap             paintBackgroundPixmap;
 
     // Preview Video Variables ////////////////////////////////////////////////
-    NuppelVideoPlayer  *previewVideoNVP;
-    RingBuffer         *previewVideoRingBuf;
-    QTimer             *previewVideoRefreshTimer;
-    MythTimer           previewVideoStartTimer;
-    MythTimer           previewVideoPlayingTimer;  
-    int                 previewVideoBrokenRecId;
-    playerStateType     previewVideoState;
-    bool                previewVideoStartTimerOn;
-    bool                previewVideoEnabled;
-    bool                previewVideoPlaying;
-    bool                previewVideoThreadRunning;
-    pthread_t           previewVideoThread;
 
-    mutable QMutex      previewVideoKillLock;
-    mutable QMutex      previewVideoUnsafeKillLock;
-    killStateType       previewVideoKillState;
-    MythTimer           previewVideoKillTimeout;
+    PIPPlayer *previewPlayer;
+    QTimer *previewVideoStartTimer; // if this elapses start the PIP.
+    QTimer *previewVideoRefreshTimer; // refresh software scaled PIP
+    bool previewVideoEnabled;
+    QMutex previewVideoLock;
+    int previewTimeout;
+    bool software_scaled; // pip is software scaled.
 
     // Preview Pixmap Variables ///////////////////////////////////////////////
     bool                previewPixmapEnabled;
