===================================================================
RCS file: ./RCS/device.c
retrieving revision 1.56
diff -u -r1.56 ./device.c
--- ./device.c	2004/06/19 08:51:05	1.56
+++ ./device.c	2004/09/26 14:13:36
@@ -149,7 +149,8 @@
   cDevice *d = NULL;
   int select = 7, pri;
 
-  for (int i = 0; i < numDevices; i++) {
+  //XXX for (int i = 0; i < numDevices; i++) {
+  for (int i = numDevices; --i >= 0; ) {//XXX FF vs. budget!
       bool ndr;
       if (device[i]->ProvidesChannel(Channel, Priority, &ndr)) { // this device is basicly able to do the job
          if (device[i]->Receiving() && !ndr)
@@ -801,79 +802,66 @@
 
 cTSBuffer::cTSBuffer(int File, int Size, int CardIndex)
 {
+  SetDescription("TS buffer on device %d", CardIndex);
   f = File;
-  size = Size / TS_SIZE * TS_SIZE;
   cardIndex = CardIndex;
-  tsRead = tsWrite = 0;
-  buf = (f >= 0 && size >= TS_SIZE) ? MALLOC(uchar, size + TS_SIZE) : NULL;
-  // the '+ TS_SIZE' allocates some extra space for handling packets that got split by a buffer roll-over
-  firstRead = true;
+  active = false;
+  delivered = false;
+  ringBuffer = new cRingBufferLinear(Size, TS_SIZE, true);
+  ringBuffer->SetTimeouts(0, 10);
+  Start();
 }
 
 cTSBuffer::~cTSBuffer()
 {
-  free(buf);
+  active = false;
+  Cancel(3);//XXX
+  delete ringBuffer;
 }
 
-int cTSBuffer::Read(void)
+void cTSBuffer::Action(void)
 {
-  if (buf) {
-     cPoller Poller(f, false);
-     bool repeat;
-     int total = 0;
-     do {
-        repeat = false;
-        if (firstRead || Used() > TS_SIZE || Poller.Poll(100)) { // only wait if there's not enough data in the buffer
-           firstRead = false;
-           if (tsRead == tsWrite)
-              tsRead = tsWrite = 0; // keep the maximum buffer space available
-           if (tsWrite >= size && tsRead > 0)
-              tsWrite = 0;
-           int free = tsRead <= tsWrite ? size - tsWrite : tsRead - tsWrite - 1;
-           if (free > 0) {
-              int r = read(f, buf + tsWrite, free);
-              if (r > 0) {
-                 total += r;
-                 tsWrite += r;
-                 if (tsWrite >= size && tsRead > 0) {
-                    tsWrite = 0;
-                    repeat = true; // read again after a boundary roll-over
-                    }
-                 }
-              }
-           }
-        } while (repeat);
-     return total;
+  if (ringBuffer) {
+     cPoller Poller(f);
+     active = true;//XXX make this part of cThread???
+     for (; active;) {
+         if (Poller.Poll(100)) {
+            int r = ringBuffer->Read(f);
+            if (r < 0 && FATALERRNO) {
+               if (errno == EOVERFLOW)
+                  esyslog("ERROR: driver buffer overflow on device %d", cardIndex);
+               else {
+                  LOG_ERROR;
+                  break;
+                  }
+               }
+            }
+         }
      }
-  return -1;
 }
 
 uchar *cTSBuffer::Get(void)
 {
-  if (Used() >= TS_SIZE) {
-     uchar *p = buf + tsRead;
+  int Count = 0;
+  if (delivered) {
+     ringBuffer->Del(TS_SIZE);
+     delivered = false;
+     }
+  uchar *p = ringBuffer->Get(Count);
+  delivered = false;
+  if (p && Count >= TS_SIZE) {
      if (*p != TS_SYNC_BYTE) {
-        esyslog("ERROR: not sync'ed to TS packet on device %d", cardIndex);
-        int tsMax = tsRead < tsWrite ? tsWrite : size;
-        for (int i = tsRead; i < tsMax; i++) {
-            if (buf[i] == TS_SYNC_BYTE) {
-               esyslog("ERROR: skipped %d bytes to sync on TS packet on device %d", i - tsRead, cardIndex);
-               tsRead = i;
-               return NULL;
+        for (int i = 1; i < Count; i++) {
+            if (p[i] == TS_SYNC_BYTE) {
+               Count = i;
+               break;
                }
             }
-        if ((tsRead = tsMax) >= size)
-           tsRead = 0;
+        ringBuffer->Del(Count);
+        esyslog("ERROR: skipped %d bytes to sync on TS packet on device %d", Count, cardIndex);
         return NULL;
         }
-     if (tsRead + TS_SIZE > size) {
-        // the packet rolled over the buffer boundary, so let's fetch the rest from the beginning (which MUST be there, since Used() >= TS_SIZE)
-        int rest = TS_SIZE - (size - tsRead);
-        memcpy(buf + size, buf, rest);
-        tsRead = rest;
-        }
-     else if ((tsRead += TS_SIZE) >= size)
-        tsRead = 0;
+     delivered = true;
      return p;
      }
   return NULL;
===================================================================
RCS file: ./RCS/device.h
retrieving revision 1.44
diff -u -r1.44 ./device.h
--- ./device.h	2004/06/19 08:50:37	1.44
+++ ./device.h	2004/09/24 14:07:22
@@ -15,6 +15,7 @@
 #include "filter.h"
 #include "nit.h"
 #include "pat.h"
+#include "ringbuffer.h"
 #include "sdt.h"
 #include "sections.h"
 #include "thread.h"
@@ -437,20 +438,17 @@
 /// sure the returned data points to a TS packet and automatically
 /// re-synchronizes after broken packets.
 
-class cTSBuffer {
+class cTSBuffer : public cThread {
 private:
   int f;
-  int size;
   int cardIndex;
-  int tsRead;
-  int tsWrite;
-  uchar *buf;
-  bool firstRead;
-  int Used(void) { return tsRead <= tsWrite ? tsWrite - tsRead : size - tsRead + tsWrite; }
+  bool active;
+  bool delivered;
+  cRingBufferLinear *ringBuffer;
+  virtual void Action(void);
 public:
   cTSBuffer(int File, int Size, int CardIndex);
   ~cTSBuffer();
-  int Read(void);
   uchar *Get(void);
   };
 
===================================================================
RCS file: ./RCS/dvbdevice.c
retrieving revision 1.93
diff -u -r1.93 ./dvbdevice.c
--- ./dvbdevice.c	2004/06/19 09:33:42	1.93
+++ ./dvbdevice.c	2004/09/26 11:28:10
@@ -1094,36 +1094,25 @@
   CloseDvr();
   fd_dvr = DvbOpen(DEV_DVB_DVR, CardIndex(), O_RDONLY | O_NONBLOCK, true);
   if (fd_dvr >= 0)
-     tsBuffer = new cTSBuffer(fd_dvr, MEGABYTE(2), CardIndex() + 1);
+     //XXX tsBuffer = new cTSBuffer(fd_dvr, MEGABYTE(2), CardIndex() + 1);
+     tsBuffer = new cTSBuffer(fd_dvr, MEGABYTE(5), CardIndex() + 1);//XXX
   return fd_dvr >= 0;
 }
 
 void cDvbDevice::CloseDvr(void)
 {
   if (fd_dvr >= 0) {
-     close(fd_dvr);
-     fd_dvr = -1;
      delete tsBuffer;
      tsBuffer = NULL;
+     close(fd_dvr);
+     fd_dvr = -1;
      }
 }
 
 bool cDvbDevice::GetTSPacket(uchar *&Data)
 {
   if (tsBuffer) {
-     int r = tsBuffer->Read();
-     if (r >= 0) {
-        Data = tsBuffer->Get();
-        return true;
-        }
-     else if (FATALERRNO) {
-        if (errno == EOVERFLOW)
-           esyslog("ERROR: DVB driver buffer overflow on device %d", CardIndex() + 1);
-        else {
-           LOG_ERROR;
-           return false;
-           }
-        }
+     Data = tsBuffer->Get();
      return true;
      }
   return false;
===================================================================
RCS file: ./RCS/recorder.c
retrieving revision 1.10
diff -u -r1.10 ./recorder.c
--- ./recorder.c	2004/03/20 10:33:21	1.10
+++ ./recorder.c	2004/09/26 15:15:17
@@ -40,7 +40,9 @@
 
   SpinUpDisk(FileName);
 
-  ringBuffer = new cRingBufferLinear(VIDEOBUFSIZE, TS_SIZE * 2, true);
+  //XXX ringBuffer = new cRingBufferLinear(VIDEOBUFSIZE, TS_SIZE * 2, true);
+  ringBuffer = new cRingBufferLinear(MEGABYTE(7), TS_SIZE * 2, true);//XXX
+  //XXX ringBuffer->SetTimeouts(0, 100);
   remux = new cRemux(VPid, APid1, APid2, DPid1, DPid2, true);
   fileName = new cFileName(FileName, true);
   recordFile = fileName->Open();
===================================================================
RCS file: ./RCS/remux.c
retrieving revision 1.18
diff -u -r1.18 ./remux.c
--- ./remux.c	2004/02/14 10:40:37	1.18
+++ ./remux.c	2004/09/19 15:51:50
@@ -133,8 +133,7 @@
   uint8_t check;
   int which;
   bool done;
-  uint8_t *resultBuffer;
-  int *resultCount;
+  cRingBufferLinear *resultBuffer;
   int tsErrors;
   int ccErrors;
   int ccCounter;
@@ -145,7 +144,7 @@
   void write_ipack(const uint8_t *Data, int Count);
   void instant_repack(const uint8_t *Buf, int Count);
 public:
-  cTS2PES(uint8_t *ResultBuffer, int *ResultCount, int Size, uint8_t AudioCid = 0x00);
+  cTS2PES(cRingBufferLinear *ResultBuffer, int Size, uint8_t AudioCid = 0x00);
   ~cTS2PES();
   void ts_to_pes(const uint8_t *Buf); // don't need count (=188)
   void Clear(void);
@@ -153,10 +152,9 @@
 
 uint8_t cTS2PES::headr[] = { 0x00, 0x00, 0x01 };
 
-cTS2PES::cTS2PES(uint8_t *ResultBuffer, int *ResultCount, int Size, uint8_t AudioCid)
+cTS2PES::cTS2PES(cRingBufferLinear *ResultBuffer, int Size, uint8_t AudioCid)
 {
   resultBuffer = ResultBuffer;
-  resultCount = ResultCount;
   size = Size;
   audioCid = AudioCid;
 
@@ -184,12 +182,9 @@
 
 void cTS2PES::store(uint8_t *Data, int Count)
 {
-  if (*resultCount + Count > RESULTBUFFERSIZE) {
-     esyslog("ERROR: result buffer overflow (%d + %d > %d)", *resultCount, Count, RESULTBUFFERSIZE);
-     Count = RESULTBUFFERSIZE - *resultCount;
-     }
-  memcpy(resultBuffer + *resultCount, Data, Count);
-  *resultCount += Count;
+  int n = resultBuffer->Put(Data, Count);
+  if (n != Count)
+     esyslog("ERROR: result buffer overflow, dropped %d out of %d byte", Count - n, Count);
 }
 
 void cTS2PES::reset_ipack(void)
@@ -452,6 +447,11 @@
 
 // --- cRemux ----------------------------------------------------------------
 
+// The minimum amount of video data necessary to identify frames:
+#define MINVIDEODATA (16*1024) // just a safe guess (max. size of any frame block, plus some safety)
+
+#define RESULTBUFFERSIZE (MINVIDEODATA * 4)
+
 cRemux::cRemux(int VPid, int APid1, int APid2, int DPid1, int DPid2, bool ExitOnFailure)
 {
   vPid = VPid;
@@ -463,13 +463,14 @@
   numUPTerrors = 0;
   synced = false;
   skipped = 0;
-  resultCount = resultDelivered = 0;
-  vTS2PES  =         new cTS2PES(resultBuffer, &resultCount, IPACKS);
-  aTS2PES1 =         new cTS2PES(resultBuffer, &resultCount, IPACKS, 0xC0);
-  aTS2PES2 = aPid2 ? new cTS2PES(resultBuffer, &resultCount, IPACKS, 0xC1) : NULL;
-  dTS2PES1 = dPid1 ? new cTS2PES(resultBuffer, &resultCount, IPACKS)       : NULL;
+  resultDelivered = 0;
+  resultBuffer = new cRingBufferLinear(RESULTBUFFERSIZE, 2 * IPACKS);
+  vTS2PES  =         new cTS2PES(resultBuffer, IPACKS);
+  aTS2PES1 =         new cTS2PES(resultBuffer, IPACKS, 0xC0);
+  aTS2PES2 = aPid2 ? new cTS2PES(resultBuffer, IPACKS, 0xC1) : NULL;
+  dTS2PES1 = dPid1 ? new cTS2PES(resultBuffer, IPACKS)       : NULL;
   //XXX don't yet know how to tell apart primary and secondary DD data...
-  dTS2PES2 = /*XXX dPid2 ? new cTS2PES(resultBuffer, &resultCount, IPACKS) : XXX*/ NULL;
+  dTS2PES2 = /*XXX dPid2 ? new cTS2PES(resultBuffer, IPACKS) : XXX*/ NULL;
 }
 
 cRemux::~cRemux()
@@ -479,6 +480,7 @@
   delete aTS2PES2;
   delete dTS2PES1;
   delete dTS2PES2;
+  delete resultBuffer;
 }
 
 int cRemux::GetPid(const uchar *Data)
@@ -527,15 +529,13 @@
   // test recording the raw TS:
   Result = Count;
   *PictureType = I_FRAME;
-  return Data;
+  return (uchar *)Data;
 XXX*/
 
   // Remove any previously delivered data from the result buffer:
 
   if (resultDelivered) {
-     if (resultDelivered < resultCount)
-        memmove(resultBuffer, resultBuffer + resultDelivered, resultCount - resultDelivered);
-     resultCount -= resultDelivered;
+     resultBuffer->Del(resultDelivered);
      resultDelivered = 0;
      }
 
@@ -560,6 +560,8 @@
          break;
       if (Data[i] != TS_SYNC_BYTE)
          break;
+      if (resultBuffer->Free() < IPACKS)
+         break;
       int pid = GetPid(Data + i + 1);
       if (Data[i + 3] & 0x10) { // got payload
          if      (pid == vPid)              vTS2PES->ts_to_pes(Data + i);
@@ -569,14 +571,14 @@
          else if (pid == dPid2 && dTS2PES2) dTS2PES2->ts_to_pes(Data + i);
          }
       used += TS_SIZE;
-      if (resultCount > (int)sizeof(resultBuffer) / 2)
-         break;
       }
   Count = used;
 
 /*XXX
   // test recording without determining the real frame borders:
   *PictureType = I_FRAME;
+  int resultCount = 0;
+  uchar *data = resultBuffer->Get(resultCount);
   Result = resultDelivered = resultCount;
   return Result ? resultBuffer : NULL;
 XXX*/
@@ -588,8 +590,10 @@
      // XXX also allowing 0x1FFF to not break Michael Paar's original patch,
      // XXX but it would probably be best to only use '0'
      *PictureType = I_FRAME;
+     int resultCount = 0;
+     uchar *data = resultBuffer->Get(resultCount);
      Result = resultDelivered = resultCount;
-     return Result ? resultBuffer : NULL;
+     return Result ? data : NULL;
      }
 
   // Check if we're getting anywhere here:
@@ -609,14 +613,16 @@
 
   *PictureType = NO_PICTURE;
 
-  if (resultCount >= MINVIDEODATA) {
-     for (int i = 0; i < resultCount; i++) {
-         if (resultBuffer[i] == 0 && resultBuffer[i + 1] == 0 && resultBuffer[i + 2] == 1) {
-            switch (resultBuffer[i + 3]) {
+  int resultCount = 0;
+  uchar *data = resultBuffer->Get(resultCount);
+  if (data && resultCount >= 2 * IPACKS) {
+     for (int i = 0; i < resultCount - 2; i++) {
+         if (data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 1) {
+            switch (data[i + 3]) {
               case VIDEO_STREAM_S ... VIDEO_STREAM_E:
                    {
                      uchar pt = NO_PICTURE;
-                     int l = ScanVideoPacket(resultBuffer, resultCount, i, pt);
+                     int l = ScanVideoPacket(data, resultCount, i, pt);
                      if (l < 0)
                         return NULL; // no useful data found, wait for more
                      if (pt != NO_PICTURE) {
@@ -628,7 +634,7 @@
                         else if (!synced) {
                            if (pt == I_FRAME) {
                               resultDelivered = i; // will drop everything before this position
-                              SetBrokenLink(resultBuffer + i, l);
+                              SetBrokenLink(data + i, l);
                               synced = true;
                               }
                            else {
@@ -640,7 +646,7 @@
                      if (synced) {
                         *PictureType = pt;
                         Result = l;
-                        uchar *p = resultBuffer + resultDelivered;
+                        uchar *p = data + resultDelivered;
                         resultDelivered += l;
                         return p;
                         }
@@ -653,12 +659,12 @@
               case PRIVATE_STREAM1:
               case AUDIO_STREAM_S ... AUDIO_STREAM_E:
                    {
-                     int l = GetPacketLength(resultBuffer, resultCount, i);
+                     int l = GetPacketLength(data, resultCount, i);
                      if (l < 0)
                         return NULL; // no useful data found, wait for more
                      if (synced) {
                         Result = l;
-                        uchar *p = resultBuffer + resultDelivered;
+                        uchar *p = data + resultDelivered;
                         resultDelivered += l;
                         return p;
                         }
===================================================================
RCS file: ./RCS/remux.h
retrieving revision 1.11
diff -u -r1.11 ./remux.h
--- ./remux.h	2004/02/14 10:40:41	1.11
+++ ./remux.h	2004/09/19 15:40:23
@@ -12,6 +12,7 @@
 
 #include <time.h> //XXX FIXME: DVB/linux/dvb/dmx.h should include <time.h> itself!!!
 #include <linux/dvb/dmx.h>
+#include "ringbuffer.h"
 #include "tools.h"
 
 // Picture types:
@@ -20,11 +21,6 @@
 #define P_FRAME    2
 #define B_FRAME    3
 
-// The minimum amount of video data necessary to identify frames:
-#define MINVIDEODATA (16*1024) // just a safe guess (max. size of any frame block, plus some safety)
-
-#define RESULTBUFFERSIZE (MINVIDEODATA * 4)
-
 class cTS2PES;
 
 class cRemux {
@@ -35,8 +31,7 @@
   int skipped;
   int vPid, aPid1, aPid2, dPid1, dPid2;
   cTS2PES *vTS2PES, *aTS2PES1, *aTS2PES2, *dTS2PES1, *dTS2PES2;
-  uchar resultBuffer[RESULTBUFFERSIZE];
-  int resultCount;
+  cRingBufferLinear *resultBuffer;
   int resultDelivered;
   int GetPid(const uchar *Data);
   int GetPacketLength(const uchar *Data, int Count, int Offset);
===================================================================
RCS file: ./RCS/ringbuffer.c
retrieving revision 1.20
diff -u -r1.20 ./ringbuffer.c
--- ./ringbuffer.c	2004/06/19 12:27:56	1.20
+++ ./ringbuffer.c	2004/09/26 15:26:40
@@ -18,11 +18,14 @@
 // --- cRingBuffer -----------------------------------------------------------
 
 #define OVERFLOWREPORTDELTA 5 // seconds between reports
+#define PERCENTAGEDELTA     10//XXX 5
+#define PERCENTAGETHRESHOLD 70//XXX 75
 
 cRingBuffer::cRingBuffer(int Size, bool Statistics)
 {
   size = Size;
   statistics = Statistics;
+  getThreadTid = 0;
   maxFill = 0;
   lastPercent = 0;
   putTimeout = getTimeout = 0;
@@ -36,6 +39,18 @@
      dsyslog("buffer stats: %d (%d%%) used", maxFill, maxFill * 100 / (size - 1));
 }
 
+void cRingBuffer::UpdatePercentage(int Fill)
+{
+  if (Fill > maxFill)
+     maxFill = Fill;
+  int percent = Fill * 100 / (Size() - 1) / PERCENTAGEDELTA * PERCENTAGEDELTA;
+  if (percent != lastPercent) {
+     if (percent > PERCENTAGETHRESHOLD || lastPercent > PERCENTAGETHRESHOLD)
+        dsyslog("buffer usage: %d%% (tid=%ld)", percent, getThreadTid);
+     lastPercent = percent;
+     }
+}
+
 void cRingBuffer::WaitForPut(void)
 {
   if (putTimeout) {
@@ -88,14 +103,17 @@
 cRingBufferLinear::cRingBufferLinear(int Size, int Margin, bool Statistics)
 :cRingBuffer(Size, Statistics)
 {
-  margin = Margin;
+  tail = head = margin = Margin;
   buffer = NULL;
-  getThreadTid = 0;
   if (Size > 1) { // 'Size - 1' must not be 0!
-     buffer = MALLOC(uchar, Size);
-     if (!buffer)
-        esyslog("ERROR: can't allocate ring buffer (size=%d)", Size);
-     Clear();
+     if (Margin < Size) {
+        buffer = MALLOC(uchar, Size);
+        if (!buffer)
+           esyslog("ERROR: can't allocate ring buffer (size=%d)", Size);
+        Clear();
+        }
+     else
+        esyslog("ERROR: illegal margin for ring buffer (%d >= %d)", Margin, Size);
      }
   else
      esyslog("ERROR: illegal size for ring buffer (%d)", Size);
@@ -108,47 +126,69 @@
 
 int cRingBufferLinear::Available(void)
 {
-  Lock();
   int diff = head - tail;
-  Unlock();
   return (diff >= 0) ? diff : Size() + diff - margin;
 }
 
 void cRingBufferLinear::Clear(void)
 {
-  Lock();
-  head = tail = margin;
+  tail = head;
   lastGet = -1;
-  Unlock();
+  maxFill = 0; //XXX cRingBuffer::Clear()???
   EnablePut();
   EnableGet();
 }
 
+int cRingBufferLinear::Read(int FileHandle, int Max)
+{
+  int Tail = tail;//XXX...
+  int diff = Tail - head;
+  int free = (diff > 0) ? diff - 1 : Size() - head;
+  if (Tail <= margin)
+     free--;
+  int Count = 0;
+  if (free > 0) {
+     if (0 < Max && Max < free)
+        free = Max;
+     Count = safe_read(FileHandle, buffer + head, free);
+     if (Count > 0) {
+        int Head = head + Count;
+        if (Head >= Size())
+           Head = margin;
+        head = Head;
+        if (statistics) {
+           int fill = head - Tail;
+           if (fill < 0)
+              fill = Size() + fill;
+           else if (fill >= Size())
+              fill = Size() - 1;
+           UpdatePercentage(fill);
+           }
+        }
+     }
+  if (Count > 0)
+     EnableGet();
+  if (free == 0)
+     WaitForPut();
+  return Count;
+}
+
 int cRingBufferLinear::Put(const uchar *Data, int Count)
 {
   if (Count > 0) {
-     Lock();
+     int Tail = tail;//XXX...
      int rest = Size() - head;
-     int diff = tail - head;
-     int free = ((tail < margin) ? rest : (diff > 0) ? diff : Size() + diff - margin) - 1;
+     int diff = Tail - head;
+     int free = ((Tail < margin) ? rest : (diff > 0) ? diff : Size() + diff - margin) - 1;
      if (statistics) {
         int fill = Size() - free - 1 + Count;
         if (fill >= Size())
            fill = Size() - 1;
-        if (fill > maxFill)
-           maxFill = fill;
-        int percent = maxFill * 100 / (Size() - 1) / 5 * 5;
-        if (abs(lastPercent - percent) >= 5) {
-           if (percent > 75)
-              dsyslog("buffer usage: %d%% (tid=%ld)", percent, getThreadTid);
-           lastPercent = percent;
-           }
+        UpdatePercentage(fill);
         }
      if (free > 0) {
         if (free < Count)
            Count = free;
-        if (Count > maxFill)
-           maxFill = Count;
         if (Count >= rest) {
            memcpy(buffer + head, Data, rest);
            if (Count - rest)
@@ -159,11 +199,10 @@
            memcpy(buffer + head, Data, Count);
            head += Count;
            }
+        EnableGet();
         }
      else
         Count = 0;
-     Unlock();
-     EnableGet();
      if (Count == 0)
         WaitForPut();
      }
@@ -173,17 +212,17 @@
 uchar *cRingBufferLinear::Get(int &Count)
 {
   uchar *p = NULL;
-  Lock();
+  int Head = head;//XXX...
   if (getThreadTid <= 0)
      getThreadTid = pthread_self();
   int rest = Size() - tail;
-  if (rest < margin && head < tail) {
+  if (rest < margin && Head < tail) {
      int t = margin - rest;
      memcpy(buffer + t, buffer + tail, rest);
      tail = t;
-     rest = head - tail;
+     rest = Head - tail;
      }
-  int diff = head - tail;
+  int diff = Head - tail;
   int cont = (diff >= 0) ? diff : Size() + diff - margin;
   if (cont > rest)
      cont = rest;
@@ -191,7 +230,6 @@
      p = buffer + tail;
      Count = lastGet = cont;
      }
-  Unlock();
   if (!p)
      WaitForGet();
   return p;
@@ -200,15 +238,15 @@
 void cRingBufferLinear::Del(int Count)
 {
   if (Count > 0 && Count <= lastGet) {
-     Lock();
-     tail += Count;
+     int Tail = tail;//XXX
+     Tail += Count;
      lastGet -= Count;
-     if (tail >= Size())
-        tail = margin;
-     Unlock();
+     if (Tail >= Size())
+        Tail = margin;
+     tail = Tail;
      EnablePut();
      }
-  else
+  else if (Count != 0)
      esyslog("ERROR: invalid Count in cRingBufferLinear::Del: %d", Count);
 }
 
===================================================================
RCS file: ./RCS/ringbuffer.h
retrieving revision 1.15
diff -u -r1.15 ./ringbuffer.h
--- ./ringbuffer.h	2004/06/19 10:32:15	1.15
+++ ./ringbuffer.h	2004/09/26 15:23:47
@@ -25,16 +25,18 @@
   int overflowCount;
   int overflowBytes;
 protected:
+  pthread_t getThreadTid;
   int maxFill;//XXX
   int lastPercent;
   bool statistics;//XXX
+  void UpdatePercentage(int Fill);
   void WaitForPut(void);
   void WaitForGet(void);
   void EnablePut(void);
   void EnableGet(void);
   virtual void Clear(void) = 0;
   virtual int Available(void) = 0;
-  int Free(void) { return size - Available() - 1; }
+  virtual int Free(void) { return Size() - Available() - 1; }
   void Lock(void) { mutex.Lock(); }
   void Unlock(void) { mutex.Unlock(); }
   int Size(void) { return size; }
@@ -50,7 +52,6 @@
   int margin, head, tail;
   int lastGet;
   uchar *buffer;
-  pthread_t getThreadTid;
 public:
   cRingBufferLinear(int Size, int Margin = 0, bool Statistics = false);
     ///< Creates a linear ring buffer.
@@ -58,8 +59,15 @@
     ///< be guaranteed to return at least Margin bytes in one consecutive block.
   virtual ~cRingBufferLinear();
   virtual int Available(void);
+  virtual int Free(void) { return Size() - Available() - 1 - margin; }
   virtual void Clear(void);
     ///< Immediately clears the ring buffer.
+  int Read(int FileHandle, int Max = 0);
+    ///< Reads at most Max bytes from FileHandle and stores them in the
+    ///< ring buffer. If Max is 0, reads as many bytes as possible.
+    ///< Only one actual read() call is done.
+    ///< \return Returns the number of bytes actually read and stored, or
+    ///< an error value from the actual read() call.
   int Put(const uchar *Data, int Count);
     ///< Puts at most Count bytes of Data into the ring buffer.
     ///< \return Returns the number of bytes actually stored.
@@ -67,7 +75,7 @@
     ///< Gets data from the ring buffer.
     ///< The data will remain in the buffer until a call to Del() deletes it.
     ///< \return Returns a pointer to the data, and stores the number of bytes
-    ///< actually retrieved in Count. If the returned pointer is NULL, Count has no meaning.
+    ///< actually available in Count. If the returned pointer is NULL, Count has no meaning.
   void Del(int Count);
     ///< Deletes at most Count bytes from the ring buffer.
     ///< Count must be less or equal to the number that was returned by a previous
===================================================================
RCS file: ./RCS/transfer.c
retrieving revision 1.16
diff -u -r1.16 ./transfer.c
--- ./transfer.c	2004/03/07 14:40:15	1.16
+++ ./transfer.c	2004/09/26 14:06:42
@@ -12,7 +12,8 @@
 //XXX+ also used in recorder.c - find a better place???
 // The size of the array used to buffer video data:
 // (must be larger than MINVIDEODATA - see remux.h)
-#define VIDEOBUFSIZE  MEGABYTE(1)
+//XXX #define VIDEOBUFSIZE  MEGABYTE(1)
+#define VIDEOBUFSIZE  MEGABYTE(3)//XXX
 #define POLLTIMEOUTS_BEFORE_DEVICECLEAR 3
 
 // --- cTransfer -------------------------------------------------------------
@@ -22,6 +23,7 @@
 ,cThread("transfer")
 {
   ringBuffer = new cRingBufferLinear(VIDEOBUFSIZE, TS_SIZE * 2, true);
+  //XXX ringBuffer->SetTimeouts(0, 100);
   remux = new cRemux(VPid, APid1, APid2, DPid1, DPid2);
   canToggleAudioTrack = false;
   audioTrack = 0xC0;
@@ -52,16 +54,10 @@
 void cTransfer::Receive(uchar *Data, int Length)
 {
   if (IsAttached()) {
-     int i = 0;
-     while (active && Length > 0) {
-           if (i++ > 10) {
-              ringBuffer->ReportOverflow(Length);
-              break;
-              }
-           int p = ringBuffer->Put(Data, Length);
-           Length -= p;
-           Data += p;
-           }
+     int p = ringBuffer->Put(Data, Length);
+     if (p != Length && active)
+        ringBuffer->ReportOverflow(Length - p);
+     return;
      }
 }
 
@@ -115,6 +111,7 @@
                        PollTimeouts++;
                        if (PollTimeouts == POLLTIMEOUTS_BEFORE_DEVICECLEAR) {
                           dsyslog("clearing device because of consecutive poll timeouts");
+                          ringBuffer->Clear();
                           DeviceClear();
                           }
                        }
