Mailing List archive

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

[vdr] [PATCH] cDvbTuner - Rev. 2



Hi,

the attached patch solves the zapping problems on my system entirely. 

The effect Wolfgang Fritz observed (FE_HAS_LOCK status disappears 
after frontend event) does not occur  on my system. Once the bit is 
set it keeps until the next tuning request. So I have focused my 
activities on changes I can test.

To reduce delays I have introduced the cCondVar evLocked to signal 
locked status and use poll() to wait for frontend event. It turned 
out that it is necessary to insert a small delay (15ms) after 
FE_HAS_LOCK status. Without, the tuning problems do reappear...

Now I am able to turn on EPG scanning over night without problems 
except ...tadaaa... the first recording is interrupted  with "video 
data stream broken" error. Maybe the 15ms delay is not enough, but it 
is hard to test because you have to wait a long time before this 
error occurs.

First of all I'm happy with this patch. The zapping problems are very 
annoying. Maybe someone can explain why the delay after detection of 
FE_HAS_LOCK status is necessary.

Stefan
--- dvbdevice.c.orig	2004-06-19 11:33:42.000000000 +0200
+++ dvbdevice.c	2004-07-29 18:59:20.000000000 +0200
@@ -35,7 +35,6 @@ extern "C" {
 
 #define DO_REC_AND_PLAY_ON_PRIMARY_DEVICE 1
 #define DO_MULTIPLE_RECORDINGS 1
-//#define WAIT_FOR_LOCK_AFTER_TUNING 1
 
 #define DEV_VIDEO         "/dev/video"
 #define DEV_DVB_ADAPTER   "/dev/dvb/adapter"
@@ -80,6 +79,7 @@ private:
   eTunerStatus tunerStatus;
   cMutex mutex;
   cCondVar newSet;
+  cCondVar evLocked;
   bool SetFrontend(void);
   virtual void Action(void);
 public:
@@ -132,6 +132,8 @@ void cDvbTuner::Set(const cChannel *Chan
      startTime = time(NULL);
   channel = *Channel;
   newSet.Broadcast();
+  if (tunerStatus < tsLocked)
+    evLocked.TimedWait(mutex, 6000);
 }
 
 static unsigned int FrequencyToHz(unsigned int f)
@@ -241,6 +243,15 @@ bool cDvbTuner::SetFrontend(void)
          esyslog("ERROR: attempt to set channel with unknown DVB frontend type");
          return false;
     }
+  
+  /* discard stale events */
+  dvb_frontend_event event;
+  while (1)
+  {
+    if (ioctl(fd_frontend, FE_GET_EVENT, &event) == -1)
+      break;
+  }
+  
   if (ioctl(fd_frontend, FE_SET_FRONTEND, &Frontend) < 0) {
      esyslog("ERROR: frontend %d: %m", cardIndex);
      return false;
@@ -248,6 +259,7 @@ bool cDvbTuner::SetFrontend(void)
   return true;
 }
 
+
 void cDvbTuner::Action(void)
 {
   active = true;
@@ -256,19 +268,28 @@ void cDvbTuner::Action(void)
         if (tunerStatus == tsSet)
            tunerStatus = SetFrontend() ? tsTuned : tsIdle;
         if (tunerStatus == tsTuned) {
-           fe_status_t status = fe_status_t(0);
-           CHECK(ioctl(fd_frontend, FE_READ_STATUS, &status));
-           if (status & FE_HAS_LOCK)
-              tunerStatus = tsLocked;
+           pollfd pfd;
+           pfd.fd = fd_frontend;
+           pfd.events = POLLIN | POLLPRI;
+           int rc = poll(&pfd, 1, 5000);
+           if (rc == 0)
+              isyslog("WARNING: frontend %d poll timed out!", cardIndex + 1);
+           else if (rc == -1)
+              esyslog("ERROR: frontend %d poll failed - errno %d!", cardIndex + 1, errno);
            }
         if (tunerStatus != tsIdle) {
            dvb_frontend_event event;
-           if (ioctl(fd_frontend, FE_GET_EVENT, &event) == 0) {
+           while (ioctl(fd_frontend, FE_GET_EVENT, &event) == 0) {
               if (event.status & FE_REINIT) {
                  tunerStatus = tsSet;
-                 esyslog("ERROR: frontend %d was reinitialized - re-tuning", cardIndex);
+                 esyslog("ERROR: frontend %d was reinitialized - re-tuning", cardIndex + 1);
                  continue;
                  }
+              if ((tunerStatus == tsTuned) && (event.status & FE_HAS_LOCK)) {
+                 tunerStatus = tsLocked;
+                 usleep(15*1000);
+                 evLocked.Broadcast();
+                 }
               }
            }
         if (ciHandler) {
@@ -293,7 +314,8 @@ void cDvbTuner::Action(void)
               tunerStatus = tsLocked;
            }
         // in the beginning we loop more often to let the CAM connection start up fast
-        newSet.TimedWait(mutex, (ciHandler && (time(NULL) - startTime < 20)) ? 100 : 1000);
+        if (tunerStatus != tsTuned)
+           newSet.TimedWait(mutex, (ciHandler && (time(NULL) - startTime < 20)) ? 100 : 1000);
         }
 }
 
@@ -748,13 +770,10 @@ bool cDvbDevice::SetChannelDevice(const 
      TurnOffLiveMode();
 
   dvbTuner->Set(Channel, DoTune, !EITScanner.UsesDevice(this)); //XXX 1.3: this is an ugly hack - find a cleaner solution//XXX
-
-#ifdef WAIT_FOR_LOCK_AFTER_TUNING
-  //XXX TODO preliminary fix for the "Unknown picture type" error
-  time_t t0 = time(NULL);
-  while (!dvbTuner->Locked() && time(NULL) - t0 < 5)
-        usleep(100);
-#endif
+  
+  if (!dvbTuner->Locked())
+    isyslog("WARNING: tuner is not locked on device %d!", CardIndex() + 1);
+  
   // PID settings:
 
   if (TurnOnLivePIDs) {

Home | Main Index | Thread Index