Index: libs/libmythtv/hdtvrecorder.h
===================================================================
--- libs/libmythtv/hdtvrecorder.h	(revision 8207)
+++ libs/libmythtv/hdtvrecorder.h	(working copy)
@@ -3,7 +3,6 @@
  *  HDTVRecorder
  *  Copyright (c) 2003-2004 by Brandon Beattie, Doug Larrick, 
  *    Jason Hoos, and Daniel Thor Kristjansson
- *  Device ringbuffer added by John Poet
  *  Distributed as part of MythTV under GPL v2 and later.
  */
 
@@ -12,6 +11,7 @@
 
 #include "dtvrecorder.h"
 #include "tsstats.h"
+#include "DeviceReadBuffer.h"
 
 struct AVFormatContext;
 struct AVPacket;
@@ -28,14 +28,12 @@
  *
  *  \sa DTVRecorder, DVBRecorder
  */
-class HDTVRecorder : public DTVRecorder
+class HDTVRecorder : public DTVRecorder, private ReaderPausedCB
 {
     Q_OBJECT
     friend class ATSCStreamData;
     friend class TSPacketProcessor;
   public:
-    enum {report_loops = 20000};
-
     HDTVRecorder(TVRec *rec);
    ~HDTVRecorder();
 
@@ -47,9 +45,6 @@
     void StartRecording(void);
     void StopRecording(void);
 
-    void Pause(bool clear = false);
-    bool IsPaused(void) const;
-
     void Reset(void);
 
     bool Open(void);
@@ -61,54 +56,41 @@
     void deleteLater(void);
 
   private:
+    bool IsOpen(void) const { return _stream_fd >= 0; }
+    bool Close(void);
+
     void TeardownAll(void);
-    int ProcessData(unsigned char *buffer, int len);
+    uint ProcessDataTS(unsigned char *buffer, uint len);
     bool ProcessTSPacket(const TSPacket& tspacket);
     void HandleVideo(const TSPacket* tspacket);
     void HandleAudio(const TSPacket* tspacket);
 
     int ResyncStream(unsigned char *buffer, int curr_pos, int len);
 
-    static void *boot_ringbuffer(void *);
-    void fill_ringbuffer(void);
-    int ringbuf_read(unsigned char *buffer, size_t count);
+    void ReaderPaused(int fd);
+    bool PauseAndWait(int timeout = 100);
 
- private slots:
+    bool readchan(int chanfd, unsigned char* buffer, int dlen);
+    bool syncchan(int chanfd, int dlen, int keepsync);
+
+  private slots:
     void WritePAT(ProgramAssociationTable*);
     void WritePMT(ProgramMapTable*);
     void ProcessMGT(const MasterGuideTable*);
     void ProcessVCT(uint, const VirtualChannelTable*);
- private:
-    ATSCStreamData* _atsc_stream_data;
 
+  private:
+    ATSCStreamData   *_atsc_stream_data;
+    DeviceReadBuffer *_drb;
+
     // statistics
-    TSStats _ts_stats;
-    long long _resync_count;
-    size_t loop;
+    TSStats           _ts_stats;
+    long long         _resync_count;
 
-    // Data for managing the device ringbuffer
-    struct {
-        pthread_t        thread;
-        mutable pthread_mutex_t lock;
-        mutable pthread_mutex_t lock_stats;
-
-        bool             run;
-        bool             eof;
-        bool             error;
-        bool             request_pause;
-        bool             paused;
-        size_t           size;
-        size_t           used;
-        size_t           max_used;
-        size_t           avg_used;
-        size_t           avg_cnt;
-        size_t           dev_read_size;
-        size_t           min_read;
-        unsigned char  * buffer;
-        unsigned char  * readPtr;
-        unsigned char  * writePtr;
-        unsigned char  * endPtr;
-    } ringbuf;
+    /// unsynced packets to look at before giving up initially
+    static const uint INIT_SYNC_WINDOW_SIZE;
+    /// synced packets to require before starting recording
+    static const uint INIT_MIN_NUM_SYNC_PACKETS;
 };
 
 #endif
Index: libs/libmythtv/hdtvrecorder.cpp
===================================================================
--- libs/libmythtv/hdtvrecorder.cpp	(revision 8207)
+++ libs/libmythtv/hdtvrecorder.cpp	(working copy)
@@ -84,13 +84,15 @@
 #include "atsctables.h"
 #include "atscstreamdata.h"
 #include "tv_rec.h"
+#include "DeviceReadBuffer.h"
 
 // AVLib/FFMPEG includes
 #include "../libavcodec/avcodec.h"
 #include "../libavformat/avformat.h"
 #include "../libavformat/mpegts.h"
 
-#define REPORT_RING_STATS 1
+#define LOC QString("HDTVRec(%1):").arg(videodevice)
+#define LOC_ERR QString("HDTVRec(%1) Error:").arg(videodevice)
 
 #define DEFAULT_SUBCHANNEL 1
 
@@ -109,6 +111,9 @@
         };
 #endif
 
+const uint HDTVRecorder::INIT_SYNC_WINDOW_SIZE     = 50;
+const uint HDTVRecorder::INIT_MIN_NUM_SYNC_PACKETS = 10;
+
 HDTVRecorder::HDTVRecorder(TVRec *rec)
     : DTVRecorder(rec, "HDTVRecorder"), _atsc_stream_data(0), _resync_count(0)
 {
@@ -116,8 +121,10 @@
     connect(_atsc_stream_data, SIGNAL(UpdatePATSingleProgram(
                                           ProgramAssociationTable*)),
             this, SLOT(WritePAT(ProgramAssociationTable*)));
-    connect(_atsc_stream_data, SIGNAL(UpdatePMTSingleProgram(ProgramMapTable*)),
-            this, SLOT(WritePMT(ProgramMapTable*)));
+    connect(_atsc_stream_data,
+            SIGNAL(UpdatePMTSingleProgram(ProgramMapTable*)),
+            this,
+            SLOT(WritePMT(ProgramMapTable*)));
     connect(_atsc_stream_data, SIGNAL(UpdateMGT(const MasterGuideTable*)),
             this, SLOT(ProcessMGT(const MasterGuideTable*)));
     connect(_atsc_stream_data,
@@ -125,30 +132,25 @@
             this, SLOT(ProcessVCT(uint, const VirtualChannelTable*)));
 
     _buffer_size = TSPacket::SIZE * 1500;
-    if ((_buffer = new unsigned char[_buffer_size])) {
-        // make valgrind happy, initialize buffer memory
+    _buffer = new unsigned char[_buffer_size];
+
+    // make valgrind happy, initialize buffer memory
+    if (_buffer)
         memset(_buffer, 0xFF, _buffer_size);
-    }
 
-    VERBOSE(VB_RECORD, QString("HD buffer size %1 KB").arg(_buffer_size/1024));
+    VERBOSE(VB_RECORD, LOC +
+            QString("buffer size %1 KB").arg(_buffer_size/1024));
 
-    ringbuf.run = false;
-    ringbuf.buffer = 0;
-    pthread_mutex_init(&ringbuf.lock, NULL);
-    pthread_mutex_init(&ringbuf.lock_stats, NULL);
-    loop = random() % (report_loops / 2);
+    _drb = new DeviceReadBuffer(this);
 }
 
 void HDTVRecorder::TeardownAll(void)
 {
-    // Make SURE that the ringbuffer thread is cleaned up
+    // Make SURE that the device read thread is cleaned up -- John Poet
     StopRecording();
 
-    if (_stream_fd >= 0)
-    {
-        close(_stream_fd);
-        _stream_fd = -1;
-    }
+    Close();
+
     if (_atsc_stream_data)
     {
         delete _atsc_stream_data;
@@ -164,8 +166,7 @@
 HDTVRecorder::~HDTVRecorder()
 {
     TeardownAll();
-    pthread_mutex_destroy(&ringbuf.lock);
-    pthread_mutex_destroy(&ringbuf.lock_stats);
+    delete _drb;
 }
 
 void HDTVRecorder::deleteLater(void)
@@ -189,37 +190,49 @@
     SetOption("vbiformat", gContext->GetSetting("VbiFormat"));
 }
 
-bool HDTVRecorder::Open()
+bool HDTVRecorder::Open(void)
 {
     if (!_atsc_stream_data || !_buffer)
         return false;
 
 #if FAKE_VIDEO
     // open file instead of device
-    if (_stream_fd >=0 && close(_stream_fd))
-    {
-        VERBOSE(VB_IMPORTANT,
-                QString("HDTVRecorder::Open(): Error, failed to close "
-                        "existing fd (%1)").arg(strerror(errno)));
-        return false;
-    }
 
+    Close(); // close old video file
     _stream_fd = open(FAKE_VIDEO_FILES[fake_video_index], O_RDWR);
-    VERBOSE(VB_IMPORTANT, QString("Opened fake video source %1").arg(FAKE_VIDEO_FILES[fake_video_index]));
-    fake_video_index = (fake_video_index+1)%FAKE_VIDEO_NUM;
+
+    VERBOSE(VB_IMPORTANT, LOC_ERR + QString("Opened fake video source '%1'")
+            .arg(FAKE_VIDEO_FILES[fake_video_index]) + ENO);
+
+    fake_video_index = (fake_video_index + 1) % FAKE_VIDEO_NUM;
+
 #else
-    if (_stream_fd <= 0)
+    if (!IsOpen())
         _stream_fd = open(videodevice.ascii(), O_RDWR);
 #endif
-    if (_stream_fd <= 0)
+
+    if (!IsOpen())
     {
-        VERBOSE(VB_IMPORTANT, QString("Can't open video device: %1 chanfd = %2")
-                .arg(videodevice).arg(_stream_fd));
-        perror("open video:");
+        VERBOSE(VB_IMPORTANT, LOC_ERR +
+                QString("Couldn't open video device: '%1'")
+                .arg(videodevice) + ENO);
     }
-    return (_stream_fd>0);
+
+    return IsOpen();
 }
 
+bool HDTVRecorder::Close(void)
+{
+    if (IsOpen() && (0 != close(_stream_fd)))
+    {
+        VERBOSE(VB_IMPORTANT, LOC_ERR +
+                "Failed to close file descriptor." + ENO);
+        return false;
+    }
+    _stream_fd = -1;
+    return true;
+}
+
 void HDTVRecorder::SetStreamData(ATSCStreamData *stream_data)
 {
     if (stream_data == _atsc_stream_data)
@@ -231,32 +244,37 @@
         delete old_data;
 }
 
-bool readchan(int chanfd, unsigned char* buffer, int dlen) {
+bool HDTVRecorder::readchan(int chanfd, unsigned char* buffer, int dlen)
+{
     int len = read(chanfd, buffer, dlen); // read next byte
     if (dlen != len)
     {
         if (len < 0)
         {
-            VERBOSE(VB_IMPORTANT, QString("HD1 error reading from device"));
-            perror("read");
+            VERBOSE(VB_IMPORTANT, LOC_ERR +
+                    "Reading from device failed" + ENO);
         }
         else if (len == 0)
-            VERBOSE(VB_IMPORTANT, QString("HD2 end of file found in packet"));
+            VERBOSE(VB_IMPORTANT, LOC_ERR + "EOF found in TS packet");
         else 
-            VERBOSE(VB_IMPORTANT, QString("HD3 partial read. This shouldn't happen!"));
+            VERBOSE(VB_IMPORTANT, LOC_ERR +
+                    "Partial read during initial TS sync phase");
     }
     return (dlen == len);
 }
 
-bool syncchan(int chanfd, int dlen, int keepsync) {
+bool HDTVRecorder::syncchan(int chanfd, int dlen, int keepsync)
+{
     unsigned char b[188];
     int i, j;
-    for (i=0; i<dlen; i++) {
+    for (i=0; i<dlen; i++)
+    {
         if (!readchan(chanfd, b, 1))
             break;
         if (SYNC_BYTE == b[0])
         {
-            if (readchan(chanfd, &b[1], TSPacket::SIZE-1)) {
+            if (readchan(chanfd, &b[1], TSPacket::SIZE-1))
+            {
                 i += (TSPacket::SIZE - 1);
                 for (j=0; j<keepsync; j++)
                 {
@@ -268,9 +286,8 @@
                 }
                 if (j==keepsync)
                 {
-                    VERBOSE(VB_RECORD,
-                            QString("HD4 obtained device stream sync after reading %1 bytes").
-                            arg(dlen));
+                    VERBOSE(VB_RECORD, LOC + "Obtained TS sync, "+
+                            QString("after reading %1 bytes").arg(dlen));
                     return true;
                 }
                 continue;
@@ -278,362 +295,72 @@
             break;
         }
     }
-    VERBOSE(VB_IMPORTANT, QString("HD5 Error: could not obtain sync"));
+    VERBOSE(VB_IMPORTANT, LOC_ERR + "Could not obtain TS sync");
     return false;
 }
 
-void * HDTVRecorder::boot_ringbuffer(void * arg)
-{
-    HDTVRecorder *dtv = (HDTVRecorder *)arg;
-    dtv->fill_ringbuffer();
-    return NULL;
-}
+#define SR_CHK(MSG) \
+    if (!ok) { VERBOSE(VB_IMPORTANT, MSG); _error = true; return; }
 
-void HDTVRecorder::fill_ringbuffer(void)
+void HDTVRecorder::StartRecording(void)
 {
-    int       errcnt = 0;
-    int       len;
-    size_t    unused, used;
-    size_t    contiguous;
-    size_t    read_size;
-    bool      run, request_pause, paused;
+    bool ok        = true;
+    uint len       = 0;
+    uint remainder = 0;
 
-    pthread_mutex_lock(&ringbuf.lock);
-    ringbuf.run = true;
-    pthread_mutex_unlock(&ringbuf.lock);
+    VERBOSE(VB_RECORD, LOC + "StartRecording()");
 
-    for (;;)
-    {
-        pthread_mutex_lock(&ringbuf.lock);
-        run = ringbuf.run;
-        unused = ringbuf.size - ringbuf.used;
-        request_pause = ringbuf.request_pause;
-        paused = ringbuf.paused;
-        pthread_mutex_unlock(&ringbuf.lock);
+    ok = Open();
+    SR_CHK("Failed to open device.");
 
-        if (!run)
-            break;
+    ok = _drb->Setup(videodevice, _stream_fd);
+    SR_CHK("Failed to allocate device read buffer.");
 
-        if (request_pause)
-        {
-            pthread_mutex_lock(&ringbuf.lock);
-            ringbuf.paused = true;
-            pthread_mutex_unlock(&ringbuf.lock);
+    ok = syncchan(_stream_fd,
+                  INIT_SYNC_WINDOW_SIZE * TSPacket::SIZE,
+                  INIT_MIN_NUM_SYNC_PACKETS);
+    SR_CHK("Failed to sync to transport stream to valid packet.");
 
-            pauseWait.wakeAll();
-            if (tvrec)
-                tvrec->RecorderPaused();
+    _drb->Start();
 
-            usleep(1000);
-            continue;
-        }
-        else if (paused)
-        {
-            pthread_mutex_lock(&ringbuf.lock);
-            ringbuf.writePtr = ringbuf.readPtr = ringbuf.buffer;
-            ringbuf.used = 0;
-            ringbuf.paused = false;
-            pthread_mutex_unlock(&ringbuf.lock);
-        }
-
-        contiguous = ringbuf.endPtr - ringbuf.writePtr;
-
-        while (unused < TSPacket::SIZE && contiguous > TSPacket::SIZE)
-        {
-            usleep(500);
-
-            pthread_mutex_lock(&ringbuf.lock);
-            unused = ringbuf.size - ringbuf.used;
-            request_pause = ringbuf.request_pause;
-            pthread_mutex_unlock(&ringbuf.lock);
-
-            if (request_pause)
-                break;
-        }
-        if (request_pause)
-            continue;
-
-        read_size = unused > contiguous ? contiguous : unused;
-        if (read_size > ringbuf.dev_read_size)
-            read_size = ringbuf.dev_read_size;
-
-        len = read(_stream_fd, ringbuf.writePtr, read_size);
-
-        if (len < 0)
-        {
-            if (errno == EINTR)
-                continue;
-
-            VERBOSE(VB_IMPORTANT, QString("HD7 error reading from %1")
-                    .arg(videodevice));
-            perror("read");
-            if (++errcnt > 5)
-            {
-                pthread_mutex_lock(&ringbuf.lock);
-                ringbuf.error = true;
-                pthread_mutex_unlock(&ringbuf.lock);
-
-                break;
-            }
-
-            usleep(500);
-            continue;
-        }
-        else if (len == 0)
-        {
-            if (++errcnt > 5)
-            {
-                VERBOSE(VB_IMPORTANT, QString("HD8 %1 end of file found.")
-                        .arg(videodevice));
-
-                pthread_mutex_lock(&ringbuf.lock);
-                ringbuf.eof = true;
-                pthread_mutex_unlock(&ringbuf.lock);
-
-                break;
-            }
-            usleep(500);
-            continue;
-        }
-
-        errcnt = 0;
-
-        pthread_mutex_lock(&ringbuf.lock);
-        ringbuf.used += len;
-        used = ringbuf.used;
-        ringbuf.writePtr += len;
-        pthread_mutex_unlock(&ringbuf.lock);
-
-#ifdef REPORT_RING_STATS
-        pthread_mutex_lock(&ringbuf.lock_stats);
-
-        if (ringbuf.max_used < used)
-            ringbuf.max_used = used;
-
-        ringbuf.avg_used = ((ringbuf.avg_used * ringbuf.avg_cnt) + used)
-                           / ++ringbuf.avg_cnt;
-        pthread_mutex_unlock(&ringbuf.lock_stats);
-#endif
-
-        if (ringbuf.writePtr == ringbuf.endPtr)
-            ringbuf.writePtr = ringbuf.buffer;
-    }
-
-    close(_stream_fd);
-    _stream_fd = -1;
-}
-
-/* read count bytes from ring into buffer */
-int HDTVRecorder::ringbuf_read(unsigned char *buffer, size_t count)
-{
-    size_t          avail;
-    size_t          cnt = count;
-    size_t          min_read;
-    unsigned char  *cPtr = buffer;
-
-    bool            dev_error = false;
-    bool            dev_eof = false;
-
-    pthread_mutex_lock(&ringbuf.lock);
-    avail = ringbuf.used;
-    pthread_mutex_unlock(&ringbuf.lock);
-
-    min_read = cnt < ringbuf.min_read ? cnt : ringbuf.min_read;
-
-    while (min_read > avail)
-    {
-        usleep(50000);
-
-        if (request_pause || dev_error || dev_eof)
-            return 0;
-
-        pthread_mutex_lock(&ringbuf.lock);
-        dev_error = ringbuf.error;
-        dev_eof = ringbuf.eof;
-        avail = ringbuf.used;
-        pthread_mutex_unlock(&ringbuf.lock);
-    }
-    if (cnt > avail)
-        cnt = avail;
-
-    if (ringbuf.readPtr + cnt > ringbuf.endPtr)
-    {
-        size_t      len;
-
-        // Process as two pieces
-        len = ringbuf.endPtr - ringbuf.readPtr;
-        memcpy(cPtr, ringbuf.readPtr, len);
-        cPtr += len;
-        len = cnt - len;
-
-        // Wrap arround to begining of buffer
-        ringbuf.readPtr = ringbuf.buffer;
-        memcpy(cPtr, ringbuf.readPtr, len);
-        ringbuf.readPtr += len;
-    }
-    else
-    {
-        memcpy(cPtr, ringbuf.readPtr, cnt);
-        ringbuf.readPtr += cnt;
-    }
-
-    pthread_mutex_lock(&ringbuf.lock);
-    ringbuf.used -= cnt;
-    pthread_mutex_unlock(&ringbuf.lock);
-
-    if (ringbuf.readPtr == ringbuf.endPtr)
-        ringbuf.readPtr = ringbuf.buffer;
-    else
-    {
-#ifdef REPORT_RING_STATS
-        size_t samples, avg, max;
-
-        if (++loop == report_loops)
-        {
-            loop = 0;
-            pthread_mutex_lock(&ringbuf.lock_stats);
-            avg = ringbuf.avg_used;
-            samples = ringbuf.avg_cnt;
-            max = ringbuf.max_used;
-            ringbuf.avg_used = 0;
-            ringbuf.avg_cnt = 0;
-            ringbuf.max_used = 0;
-            pthread_mutex_unlock(&ringbuf.lock_stats);
-
-            VERBOSE(VB_IMPORTANT, QString("%1 ringbuf avg %2% max %3%"
-                                          " samples %4")
-                    .arg(videodevice)
-                    .arg((static_cast<double>(avg)
-                          / ringbuf.size) * 100.0)
-                    .arg((static_cast<double>(max)
-                          / ringbuf.size) * 100.0)
-                    .arg(samples));
-        }
-        else
-#endif
-            usleep(25);
-    }
-
-    return cnt;
-}
-
-void HDTVRecorder::StartRecording(void)
-{
-    bool            pause;
-    bool            dev_error, dev_eof;
-    int             len;
-
-    const int unsyncpackets = 50; // unsynced packets to look at before giving up
-    const int syncpackets   = 10; // synced packets to require before starting recording
-
-    VERBOSE(VB_RECORD, QString("StartRecording"));
-
-    if (!Open())
-    {
-        _error = true;        
-        return;
-    }
-
     _request_recording = true;
-    _recording = true;
+    _recording         = true;
 
-    // Setup device ringbuffer
-    delete[] ringbuf.buffer;
-
-//    ringbuf.size = 60 * 1024 * TSPacket::SIZE;
-    ringbuf.size = gContext->GetNumSetting("HDRingbufferSize", 50*188);
-    ringbuf.size *= 1024;
-
-    if ((ringbuf.buffer =
-         new unsigned char[ringbuf.size + TSPacket::SIZE]) == NULL)
+    // Process packets while recording is requested
+    while (_request_recording && !_error)
     {
-        VERBOSE(VB_IMPORTANT, "Failed to allocate HDTVRecorder ring buffer.");
-        _error = true;
-        return;
-    }
-
-    memset(ringbuf.buffer, 0xFF, ringbuf.size + TSPacket::SIZE);
-    ringbuf.endPtr = ringbuf.buffer + ringbuf.size;
-    ringbuf.readPtr = ringbuf.writePtr = ringbuf.buffer;
-    ringbuf.dev_read_size = TSPacket::SIZE * 48;
-    ringbuf.min_read = TSPacket::SIZE * 4;
-    ringbuf.used = 0;
-    ringbuf.max_used = 0;
-    ringbuf.avg_used = 0;
-    ringbuf.avg_cnt = 0;
-    ringbuf.request_pause = false;
-    ringbuf.paused = false;
-    ringbuf.error = false;
-    ringbuf.eof = false;
-
-    VERBOSE(VB_RECORD, QString("HD ring buffer size %1 KB")
-            .arg(ringbuf.size/1024));
-
-    // sync device stream so it starts with a valid ts packet
-    if (!syncchan(_stream_fd, TSPacket::SIZE*unsyncpackets, syncpackets))
-    {
-        _error = true;
-        return;
-    }
-
-    // create thread to fill the ringbuffer
-    pthread_create(&ringbuf.thread, NULL, boot_ringbuffer,
-                   reinterpret_cast<void *>(this));
-
-    int remainder = 0;
-    // TRANSFER DATA
-    while (_request_recording) 
-    {
-        pthread_mutex_lock(&ringbuf.lock);
-        dev_error = ringbuf.error;
-        dev_eof = ringbuf.eof;
-        pause = ringbuf.paused;
-        pthread_mutex_unlock(&ringbuf.lock);
-
-        if (request_pause)
-        {
-            pthread_mutex_lock(&ringbuf.lock);
-            ringbuf.request_pause = true;
-            pthread_mutex_unlock(&ringbuf.lock);
-
-            usleep(1000);
+        if (PauseAndWait())
             continue;
-        }
-        else if (pause)
-        {
-            pthread_mutex_lock(&ringbuf.lock);
-            ringbuf.request_pause = false;
-            pthread_mutex_unlock(&ringbuf.lock);
 
-            usleep(1500);
-            continue;
-        }
+        len = _drb->Read(&(_buffer[remainder]), _buffer_size - remainder);
 
-        if (dev_error)
-        {
-            VERBOSE(VB_IMPORTANT, "HDTV: device error detected");
-            _error = true;
-            break;
-        }
-
-        if (dev_eof)
-            break;
-
-        len = ringbuf_read(&(_buffer[remainder]), _buffer_size - remainder);
-
         if (len == 0)
             continue;
 
         len += remainder;
-        remainder = ProcessData(_buffer, len);
+        remainder = ProcessDataTS(_buffer, len);
         if (remainder > 0) // leftover bytes
             memmove(_buffer, &(_buffer[_buffer_size - remainder]),
                     remainder);
+
+        // Check for DRB errors
+        if (_drb->IsErrored())
+        {
+            VERBOSE(VB_IMPORTANT, LOC_ERR + "Device error detected");
+            _error = true;
+        }
+
+        if (_drb->IsEOF())
+        {
+            VERBOSE(VB_IMPORTANT, LOC_ERR + "Device EOF detected");
+            _error = true;
+        }
     }
 
     FinishRecording();
     _recording = false;
 }
+#undef SR_CHK
 
 void HDTVRecorder::StopRecording(void)
 {
@@ -649,42 +376,47 @@
 
     _request_recording = false;
 
-    pthread_mutex_lock(&ringbuf.lock);
-    bool run = ringbuf.run;
-    ringbuf.run = false;
-    pthread_mutex_unlock(&ringbuf.lock);
+    if (_drb && _drb->IsRunning())
+        _drb->Stop();
 
-    if (run)
-        pthread_join(ringbuf.thread, NULL);
+    while (_recording)
+        usleep(2000);
 
-    if (!ok)
-    {
-        // Better to have a memory leak, then a segfault?
-        VERBOSE(VB_IMPORTANT, "DTV ringbuffer not cleaned up!\n");
-    }
-    else
-    {
-        delete[] ringbuf.buffer;
-        ringbuf.buffer = 0;
-    }
     tvrec = rec;
 }
 
-void HDTVRecorder::Pause(bool /*clear*/)
+void HDTVRecorder::ReaderPaused(int /*fd*/)
 {
-    pthread_mutex_lock(&ringbuf.lock);
-    ringbuf.paused = false;
-    pthread_mutex_unlock(&ringbuf.lock);
-    request_pause = true;
+    pauseWait.wakeAll();
+    if (tvrec)
+        tvrec->RecorderPaused();
 }
 
-bool HDTVRecorder::IsPaused(void) const
+bool HDTVRecorder::PauseAndWait(int timeout)
 {
-    pthread_mutex_lock(&ringbuf.lock);
-    bool paused = ringbuf.paused;
-    pthread_mutex_unlock(&ringbuf.lock);
+#ifdef USE_DRB
+    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;
+#else // if !USE_DRB
+    return RecorderBase::PauseAndWait(timeout);
+#endif // !USE_DRB
 }
 
 int HDTVRecorder::ResyncStream(unsigned char *buffer, int curr_pos, int len)
@@ -695,7 +427,8 @@
     if (nextpos >= len)
         return -1; // not enough bytes; caller should try again
     
-    while (buffer[pos] != SYNC_BYTE || buffer[nextpos] != SYNC_BYTE) {
+    while (buffer[pos] != SYNC_BYTE || buffer[nextpos] != SYNC_BYTE)
+    {
         pos++;
         nextpos++;
         if (nextpos == len)
@@ -707,81 +440,22 @@
 
 void HDTVRecorder::WritePAT(ProgramAssociationTable *pat)
 {
+    if (!pat)
+        return;
+
     int next = (pat->tsheader()->ContinuityCounter()+1)&0xf;
     pat->tsheader()->SetContinuityCounter(next);
     ringBuffer->Write(pat->tsheader()->data(), TSPacket::SIZE);
 }
 
-#if WHACK_A_BUG_VIDEO
-static int WABV_base_pid     = 0x100;
-#define WABV_WAIT 60
-static int WABV_wait_a_while = WABV_WAIT;
-bool WABV_started = false;
-#endif
-
-#if WHACK_A_BUG_AUDIO
-static int WABA_base_pid     = 0x200;
-#define WABA_WAIT 60
-static int WABA_wait_a_while = WABA_WAIT;
-bool WABA_started = false;
-#endif
-
 void HDTVRecorder::WritePMT(ProgramMapTable* pmt)
 {
-    if (pmt) {
-        int next = (pmt->tsheader()->ContinuityCounter()+1)&0xf;
-        pmt->tsheader()->SetContinuityCounter(next);
+    if (!pmt)
+        return;
 
-#if WHACK_A_BUG_VIDEO
-        WABV_wait_a_while--;
-        if (WABV_wait_a_while<=0) {
-            WABV_started = true;
-            WABV_wait_a_while = WABV_WAIT;
-            WABV_base_pid = (((WABV_base_pid-0x100)+1)%32)+0x100;
-            if (StreamID::MPEG2Video != StreamData()->PMT()->StreamType(0))
-            {
-                VERBOSE(VB_IMPORTANT, "HDTVRecorder::WritePMT(): Error,"
-                        "Whack a Bug can not rewrite PMT, wrong stream type");
-            }
-            else
-            {
-                VERBOSE(VB_IMPORTANT, QString("Whack a Bug: new video pid %1").
-                        arg(WABV_base_pid));
-                // rewrite video pid
-                const uint old_video_pid=StreamData()->PMT()->StreamPID(0);
-                StreamData()->PMT()->SetStreamPID(0, WABV_base_pid);
-                if (StreamData()->PMT()->PCRPID() == old_video_pid)
-                    StreamData()->PMT()->SetPCRPID(WABV_base_pid);
-                StreamData()->PMT()->SetCRC(StreamData()->PMT()->CalcCRC());
-                VERBOSE(VB_IMPORTANT, StreamData()->PMT()->toString());
-            }
-        }
-#endif
-#if WHACK_A_BUG_AUDIO
-        WABA_wait_a_while--;
-        if (WABA_wait_a_while<=0) {
-            WABA_started = true;
-            WABA_wait_a_while = WABA_WAIT;
-            WABA_base_pid = (((WABA_base_pid-0x200)+1)%32)+0x200;
-            VERBOSE(VB_IMPORTANT, QString("Whack a Bug: new audio BASE pid %1").arg(WABA_base_pid));
-            // rewrite audio pids
-            for (uint i=0; i<StreamData()->PMT()->StreamCount(); i++) {
-                if (StreamID::MPEG2Audio == StreamData()->PMT()->StreamType(i) ||
-                    StreamID::MPEG2Audio == StreamData()->PMT()->StreamType(i)) {
-                    const uint old_audio_pid = StreamData()->PMT()->StreamPID(i);
-                    const uint new_audio_pid = WABA_base_pid + old_audio_pid;
-                    StreamData()->PMT()->SetStreamPID(i, new_audio_pid);
-                    if (StreamData()->PMT()->PCRPID() == old_audio_pid)
-                        StreamData()->PMT()->SetPCRPID(new_audio_pid);
-                    StreamData()->PMT()->SetCRC(StreamData()->PMT()->CalcCRC());
-                    VERBOSE(VB_IMPORTANT, StreamData()->PMT()->toString());
-                }
-            }
-        }
-#endif
-
-        ringBuffer->Write(pmt->tsheader()->data(), TSPacket::SIZE);
-    }
+    int next = (pmt->tsheader()->ContinuityCounter()+1)&0xf;
+    pmt->tsheader()->SetContinuityCounter(next);
+    ringBuffer->Write(pmt->tsheader()->data(), TSPacket::SIZE);
 }
 
 /** \fn HDTVRecorder::ProcessMGT(const MasterGuideTable*)
@@ -820,9 +494,8 @@
         {
             if (vct->ProgramNumber(i) != (uint)StreamData()->DesiredProgram())
             {
-                VERBOSE(VB_RECORD, 
-                        QString("Resetting desired program from %1"
-                                " to %2")
+                VERBOSE(VB_RECORD, LOC_ERR +
+                        QString("Resetting desired program from %1 to %2")
                         .arg(StreamData()->DesiredProgram())
                         .arg(vct->ProgramNumber(i)));
                 // Do a (partial?) reset here if old desired
@@ -834,14 +507,14 @@
     }
     if (!found)
     {
-        VERBOSE(VB_IMPORTANT, 
+        VERBOSE(VB_IMPORTANT, LOC_ERR + 
                 QString("Desired channel %1_%2 not found;"
                         " using %3_%4 instead.")
                 .arg(StreamData()->DesiredMajorChannel())
                 .arg(StreamData()->DesiredMinorChannel())
                 .arg(vct->MajorChannel(0))
-                .arg(vct->MinorChannel(0)));
-        VERBOSE(VB_IMPORTANT, vct->toString());
+                .arg(vct->MinorChannel(0)) + "\n" + vct->toString());
+
         StreamData()->SetDesiredProgram(vct->ProgramNumber(0));
     }
 }
@@ -854,11 +527,6 @@
     if (_wait_for_keyframe && !_keyframe_seen)
         return;
 
-#if WHACK_A_BUG_VIDEO
-    if (WABV_started)
-        ((TSPacket*)(tspacket))->SetPID(WABV_base_pid);
-#endif
-
     ringBuffer->Write(tspacket->data(), TSPacket::SIZE);
 }
 
@@ -868,11 +536,6 @@
     if (_wait_for_keyframe && !_keyframe_seen)
         return;
 
-#if WHACK_A_BUG_AUDIO
-    if (WABA_started)
-        ((TSPacket*)(tspacket))->SetPID(WABA_base_pid+tspacket->PID());
-#endif
-
     ringBuffer->Write(tspacket->data(), TSPacket::SIZE);
 }
 
@@ -902,19 +565,29 @@
     return ok;
 }
 
-int HDTVRecorder::ProcessData(unsigned char *buffer, int len)
+uint HDTVRecorder::ProcessDataTS(unsigned char *buffer, uint len)
 {
-    int pos = 0;
+    if (len < TSPacket::SIZE)
+        return len;
 
-    while (pos + 187 < len) // while we have a whole packet left
+    uint pos = 0;
+    uint end = len - TSPacket::SIZE;
+    while (pos <= end) // while we have a whole packet left
     {
         if (buffer[pos] != SYNC_BYTE)
         {
             _resync_count++;
-            if (25 == _resync_count) 
-                VERBOSE(VB_RECORD, QString("Resyncing many of times, suppressing error messages"));
+
+            if (25 == _resync_count)
+            {
+                VERBOSE(VB_RECORD, LOC + "Resyncing many of times, "
+                        "suppressing error messages");
+            }
             else if (25 > _resync_count)
-                VERBOSE(VB_RECORD, QString("Resyncing"));
+            {
+                VERBOSE(VB_RECORD, LOC + "Resyncing");
+            }
+
             int newpos = ResyncStream(buffer, pos, len);
             if (newpos == -1)
                 return len - pos;
@@ -925,13 +598,21 @@
         }
 
         const TSPacket *pkt = reinterpret_cast<const TSPacket*>(&buffer[pos]);
-        if (ProcessTSPacket(*pkt)) {
-            pos += TSPacket::SIZE; // Advance to next TS packet
+        if (ProcessTSPacket(*pkt))
+        {
+            // Advance to next TS packet
+            pos += TSPacket::SIZE;
+
+            // Take care of statistics
             _ts_stats.IncrTSPacketCount();
-            if (0 == _ts_stats.TSPacketCount()%1000000)
-                VERBOSE(VB_RECORD, _ts_stats.toString());
-        } else // Let it resync in case of dropped bytes
-            buffer[pos] = SYNC_BYTE+1;
+            if (0 == _ts_stats.TSPacketCount() % 1000000)
+                VERBOSE(VB_RECORD, LOC + "\n" + _ts_stats.toString());
+
+        }
+        else
+        {
+            pos++; // Resync on invalid packet, in case of dropped bytes...
+        }
     }
 
     return len - pos;
@@ -939,7 +620,7 @@
 
 void HDTVRecorder::Reset(void)
 {
-    VERBOSE(VB_RECORD, "HDTVRecorder::Reset(void)");
+    VERBOSE(VB_RECORD, LOC + "Reset(void)");
     DTVRecorder::Reset();
 
     _error = false;
@@ -947,46 +628,28 @@
     _ts_stats.Reset();
 
     if (curRecording)
-    {
         curRecording->ClearPositionMap(MARK_GOP_BYFRAME);
+
+    if (!IsOpen())
+        return /* true */;
+
+    if (!IsPaused())
+    {
+        Pause();
+        WaitForPause();
     }
 
-    if (_stream_fd >= 0) 
+    if (!Close())
+        return /* false */;
+
+    if (Open())
     {
-        if (!IsPaused())
-        {
-            Pause();
-            WaitForPause();
-        }
-        int ret = close(_stream_fd);
-        if (ret < 0) 
-        {
-            perror("close");
-            return;
-        }
-#if FAKE_VIDEO
-        // open file instead of device
-        _stream_fd = open(FAKE_VIDEO_FILES[fake_video_index], O_RDWR);
-        VERBOSE(VB_IMPORTANT, QString("Opened fake video source %1").arg(FAKE_VIDEO_FILES[fake_video_index]));
-        fake_video_index = (fake_video_index+1)%FAKE_VIDEO_NUM;
-#else
-        _stream_fd = open(videodevice.ascii(), O_RDWR);
-#endif
-        if (_stream_fd < 0)
-        {
-            VERBOSE(VB_IMPORTANT, QString("HD1 Can't open video device: %1 chanfd = %2").
-                    arg(videodevice).arg(_stream_fd));
-            perror("open video");
-            return;
-        }
-        else
-        {
-            pthread_mutex_lock(&ringbuf.lock);
-            ringbuf.used = 0;
-            ringbuf.max_used = 0;
-            ringbuf.readPtr = ringbuf.writePtr = ringbuf.buffer;
-            pthread_mutex_unlock(&ringbuf.lock);
-        }
+        _drb->Reset(videodevice, _stream_fd);
         Unpause();
+        return /* true */;
     }
+
+    VERBOSE(VB_IMPORTANT, LOC_ERR + "Couldn't open video device: " +
+            QString("'%1'").arg(videodevice) + ENO);
+    return /* false */;
 }
