Index: libs/libmythtv/mpegrecorder.h
===================================================================
--- libs/libmythtv/mpegrecorder.h	(revision 9756)
+++ libs/libmythtv/mpegrecorder.h	(working copy)
@@ -4,11 +4,12 @@
 #define MPEGRECORDER_H_
 
 #include "recorderbase.h"
+#include "DeviceReadBuffer.h"
 
 struct AVFormatContext;
 struct AVPacket;
 
-class MpegRecorder : public RecorderBase
+class MpegRecorder : public RecorderBase, private ReaderPausedCB
 {
   public:
     MpegRecorder(TVRec*);
@@ -56,12 +57,15 @@
 
     void ResetForNewFile(void);
 
+    void ReaderPaused(int fd);
+    bool PauseAndWait(int timeout = 100);
+
     bool deviceIsMpegFile;
     int bufferSize;
 
     // State
     bool recording;
-    bool encoding;
+    bool request_recording;
     bool errored;
 
     // Pausing state
@@ -79,6 +83,7 @@
     // Input file descriptors
     int chanfd;
     int readfd;
+    DeviceReadBuffer *drb;
 
     // Keyframe tracking inforamtion
     int keyframedist;
Index: libs/libmythtv/mpegrecorder.cpp
===================================================================
--- libs/libmythtv/mpegrecorder.cpp	(revision 9756)
+++ libs/libmythtv/mpegrecorder.cpp	(working copy)
@@ -73,7 +73,7 @@
     deviceIsMpegFile(false),
     bufferSize(4096),
     // State
-    recording(false),         encoding(false),
+    recording(false),         request_recording(false),
     errored(false),
     // Pausing state
     cleartimeonpause(false),
@@ -88,6 +88,7 @@
     audvolume(80),
     // Input file descriptors
     chanfd(-1),               readfd(-1),
+    drb(NULL),
     // Keyframe tracking inforamtion
     keyframedist(15),         gopset(false),
     leftovers(0),             lastpackheaderpos(0),
@@ -98,6 +99,7 @@
     buildbuffer(new unsigned char[kBuildBufferMaxSize + 1]),
     buildbuffersize(0)
 {
+    drb = new DeviceReadBuffer(this);
 }
 
 MpegRecorder::~MpegRecorder()
@@ -113,11 +115,18 @@
         close(chanfd);
         chanfd = -1;
     }
+
     if (readfd >= 0)
     {
         close(readfd);
         readfd = -1;
     }
+
+    if (drb)
+    {
+        delete drb;
+        drb = NULL;
+    }
 }
 
 void MpegRecorder::SetOption(const QString &opt, int value)
@@ -462,7 +471,7 @@
 	return;
     }
 
-    encoding = true;
+    request_recording = true;
     recording = true;
     unsigned char *buffer = new unsigned char[bufferSize + 1];
     int ret;
@@ -470,13 +479,10 @@
     MythTimer elapsedTimer;
     float elapsed;
 
-    struct timeval tv;
-    fd_set rdset;
-
     if (deviceIsMpegFile)
         elapsedTimer.start();
 
-    while (encoding)
+    while (deviceIsMpegFile && request_recording && !errored)
     {
         if (PauseAndWait(100))
             continue;
@@ -494,39 +500,9 @@
         if (readfd < 0)
             readfd = open(videodevice.ascii(), O_RDWR);
 
-        tv.tv_sec = 5;
-        tv.tv_usec = 0;
-        FD_ZERO(&rdset);
-        FD_SET(readfd, &rdset);
-
-        switch (select(readfd + 1, &rdset, NULL, NULL, &tv))
-        {
-            case -1:
-                if (errno == EINTR)
-                    continue;
-
-                VERBOSE(VB_IMPORTANT, LOC_ERR + "Select error" + ENO);
-                continue;
-
-            case 0:
-                VERBOSE(VB_IMPORTANT, LOC_ERR + "select timeout - "
-                        "ivtv driver has stopped responding");
-
-                if (close(readfd) != 0)
-                {
-                    VERBOSE(VB_IMPORTANT, LOC_ERR + "Close error" + ENO);
-                }
-
-                readfd = -1; // Force PVR card to be reopened on next iteration
-                continue;
-
-           default: break;
-        }
-
         ret = read(readfd, buffer, bufferSize);
 
-        if ((ret == 0) &&
-            (deviceIsMpegFile))
+        if (ret == 0)
         {
             close(readfd);
             readfd = open(videodevice.ascii(), O_RDONLY);
@@ -535,7 +511,7 @@
                 ret = read(readfd, buffer, bufferSize);
             if (ret <= 0)
             {
-                encoding = false;
+                request_recording = false;
                 continue;
             }
         }
@@ -552,12 +528,84 @@
         }
     }
 
+    if (!deviceIsMpegFile)
+    {
+        VERBOSE(VB_IMPORTANT, QString("DRB:Setup(%1, %2)")
+                .arg(videodevice).arg(readfd));
+        if (!drb->Setup(videodevice, readfd))
+        {
+            VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to allocate DRB buffer");
+            //Close();
+            errored = true;
+        }
+        else
+        {
+            drb->Start();
+        }
+    }
+
+    while (request_recording && !errored && !deviceIsMpegFile)
+    {
+        if (PauseAndWait(100))
+            continue;
+
+        ssize_t len = drb->Read(buffer, bufferSize);
+        if (len > 0)
+        {
+            ProcessData(buffer, len);
+        }
+        else if (len == 0)
+        {
+            // Recover from timeout error by reopening ivtv device.
+            VERBOSE(VB_IMPORTANT, LOC_ERR + "Driver has stopped responding.");
+            /*
+            drb->Stop();
+            if (close(readfd) != 0)
+                VERBOSE(VB_IMPORTANT, LOC_ERR + "Close error" + ENO);
+            readfd = open(videodevice.ascii(), O_RDWR);
+            if (readfd < 0)
+                errored = true;
+            drb->Reset(videodevice, readfd);
+            drb->Start();
+            */
+        }
+
+        // Check for DRB errors
+        if (drb->IsErrored())
+        {
+            VERBOSE(VB_IMPORTANT, LOC_ERR + "Device error detected");
+            errored = true;
+        }
+
+        if (drb->IsEOF())
+        {
+            VERBOSE(VB_IMPORTANT, LOC_ERR + "Device EOF detected");
+            errored = true;
+        }
+    }
+
+    if (drb && drb->IsRunning())
+        drb->Stop();
+
+    //Close();
+
     FinishRecording();
 
     delete[] buffer;
     recording = false;
 }
 
+void MpegRecorder::StopRecording(void)
+{
+    request_recording = false;
+
+    if (drb && drb->IsRunning())
+        drb->Stop();
+
+    while (recording)
+        usleep(2000);
+}
+
 bool MpegRecorder::SetupRecording(void)
 {
     leftovers = 0xFFFFFFFF;
@@ -664,11 +712,6 @@
     buildbuffersize += leftlen;
 }
 
-void MpegRecorder::StopRecording(void)
-{
-    encoding = false;
-}
-
 void MpegRecorder::ResetForNewFile(void)
 {
     errored = false;
@@ -694,10 +737,39 @@
 void MpegRecorder::Pause(bool clear)
 {
     cleartimeonpause = clear;
-    paused = false;
-    request_pause = true;
+    RecorderBase::Pause(clear);
 }
 
+void MpegRecorder::ReaderPaused(int /*fd*/)
+{
+    pauseWait.wakeAll();
+    if (tvrec)
+        tvrec->RecorderPaused();
+}
+
+bool MpegRecorder::PauseAndWait(int timeout)
+{
+    if (request_pause)
+    {
+        paused = true;
+        if (!drb->IsPaused())
+            drb->SetRequestPause(true);
+
+        unpauseWait.wait(timeout);
+    }
+    else if (drb->IsPaused())
+    {
+        drb->SetRequestPause(false);
+        drb->WaitForUnpause(timeout);
+        paused = drb->IsPaused();
+    }
+    else
+    {
+        paused = false;
+    }
+    return paused;
+}
+
 long long MpegRecorder::GetKeyframePosition(long long desired)
 {
     QMutexLocker locker(&positionMapLock);
