Mailing List archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[vdr] workaround for ring buffer overflow



Hi,

as i'm also harmed by these bloody ring buffer overflows, especailly when 
doing multiple recordings on my single-card system, i've tried to find a way 
to let my vdr run more stable under these conditions. Adding some more 
logging output shows me, that these errors could be detected in the 'Action' 
function of cTransfer: if the driver has a problem, the call to DevicePoll 
returns with 0 and errno also 0, which means there was a timeout. Counting 
consecutive poll-timeouts and doing a DeviceClear after some consecutive 
timeouts helps the driver to switch back to a usable state. In the last 
resort, there will be initiated an emergency exit on more consecutive 
timeouts (never happend on my system).
The number of consecutive timeouts could be adjusted by changing the value of 
the define of POLLTIMEOUTS_BEFORE_DEVICECLEAR, the emergency exit is 
initiated by detecting twice of POLLTIMEOUTS_BEFORE_DEVICECLEAR timeouts. To 
avoid the emergency exit, just comment out the line with the define of 
EMERGENCY_EXIT_ON_CONSECUTIVE_POLLTIMEOUTS in transfer.c.

With this patch, i can do up to three recordings on different channels and 
switch between them without any problem.

Greetings

--- vdr-1.2.1/transfer.c	2003-06-14 10:40:43.000000000 +0200
+++ vdr-1.2.1patch/transfer.c	2003-06-26 22:04:20.000000000 +0200
@@ -13,6 +13,8 @@
 // The size of the array used to buffer video data:
 // (must be larger than MINVIDEODATA - see remux.h)
 #define VIDEOBUFSIZE  MEGABYTE(1)
+#define POLLTIMEOUTS_BEFORE_DEVICECLEAR 3
+#define EMERGENCY_EXIT_ON_CONSECUTIVE_POLLTIMEOUTS
 
 // --- cTransfer -------------------------------------------------------------
 
@@ -53,7 +55,7 @@
      int i = 0;
      while (active && Length > 0) {
            if (i++ > 10) {
-              esyslog("ERROR: ring buffer overflow (%d bytes dropped)", Length);
+              esyslog("ERROR: ring buffer overflow in cTransfer (%d bytes dropped)", Length);
               break;
               }
            int p = ringBuffer->Put(Data, Length);
@@ -68,6 +70,7 @@
   dsyslog("transfer thread started (pid=%d)", getpid());
 
   active = true;
+  int iPollErr = 0;
   while (active) {
 
         //XXX+ Maybe we need this to avoid buffer underruns in driver.
@@ -99,6 +102,7 @@
               while (Result > 0 && active) {
                     cPoller Poller;
                     if (DevicePoll(Poller, 100)) {
+                       iPollErr = 0;
                        int w = PlayVideo(p, Result);
                        if (w > 0) {
                           p += w;
@@ -109,6 +113,20 @@
                           break;
                           }
                        }
+		    else {
+		       iPollErr++;
+		       if( iPollErr == POLLTIMEOUTS_BEFORE_DEVICECLEAR ) {
+		         dsyslog("clear device because of consecutive poll-errors");
+		         DeviceClear();
+			 }
+		       #ifdef EMERGENCY_EXIT_ON_CONSECUTIVE_POLLERRORS
+		       if( iPollErr == POLLTIMEOUTS_BEFORE_DEVICECLEAR*2 ) {
+		         dsyslog("more consecutive poll-errors");
+                         cThread::EmergencyExit(true);
+			 }
+		       #endif
+		       }
+
                     }
               }
            }

Home | Main Index | Thread Index