Mailing List archive

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

[vdr] Fixed tuner lock detection



Attached is what I believe is the extract of all the suggested
patches to fix problems with tuning of DVB cards.

Those who have had problems in that area in the past, and had
them fixed with (some combination of) the patches that were
floating around lately should please try plain vanilla VDR 1.3.13
with this patch (and nothing else), and let me know whether this
still fixes their problems, or whether there is yet another thing
that needs to be done.

Note that the log message in case there is no lock may report
a channel number of '0' - these are raw transponders which
are found in the NIT. I'll probably check for 0 here, but at the moment
it doesn't hurt.

Klaus
--- dvbdevice.c	2004/10/17 09:10:43	1.97
+++ dvbdevice.c	2004/10/22 14:55:10
@@ -35,7 +35,7 @@
 
 #define DO_REC_AND_PLAY_ON_PRIMARY_DEVICE 1
 #define DO_MULTIPLE_RECORDINGS 1
-//#define WAIT_FOR_LOCK_AFTER_TUNING 1
+#define TUNER_LOCK_TIMEOUT 5000 // ms
 
 #define DEV_VIDEO         "/dev/video"
 #define DEV_DVB_ADAPTER   "/dev/dvb/adapter"
@@ -78,6 +78,8 @@
   bool useCa;
   time_t startTime;
   eTunerStatus tunerStatus;
+  cMutex mutex;
+  cCondVar locked;
   cCondWait newSet;
   bool SetFrontend(void);
   virtual void Action(void);
@@ -86,7 +88,7 @@
   virtual ~cDvbTuner();
   bool IsTunedTo(const cChannel *Channel) const;
   void Set(const cChannel *Channel, bool Tune, bool UseCa);
-  bool Locked(void) { return tunerStatus >= tsLocked; }
+  bool Locked(int TimeoutMs = 0);
   };
 
 cDvbTuner::cDvbTuner(int Fd_Frontend, int CardIndex, fe_type_t FrontendType, cCiHandler *CiHandler)
@@ -125,7 +127,7 @@
   if (Tune)
      tunerStatus = tsSet;
   else if (tunerStatus == tsCam)
-     tunerStatus = tsTuned;
+     tunerStatus = tsLocked;
   useCa = UseCa;
   if (Channel->Ca() && tunerStatus != tsCam)
      startTime = time(NULL);
@@ -134,6 +136,14 @@
   newSet.Signal();
 }
 
+bool cDvbTuner::Locked(int TimeoutMs)
+{
+  cMutexLock MutexLock(&mutex);
+  if (TimeoutMs && tunerStatus < tsLocked)
+     locked.TimedWait(mutex, TimeoutMs);
+  return tunerStatus >= tsLocked;
+}
+
 static unsigned int FrequencyToHz(unsigned int f)
 {
   while (f && f < 1000000)
@@ -253,22 +263,25 @@
   active = true;
   while (active) {
         Lock();
-        if (tunerStatus == tsSet)
+        if (tunerStatus == tsSet) {
+           dvb_frontend_event event;
+           while (ioctl(fd_frontend, FE_GET_EVENT, &event) == 0)
+                 ; // discard stale events
            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;
            }
         if (tunerStatus != tsIdle) {
            dvb_frontend_event event;
-           if (ioctl(fd_frontend, FE_GET_EVENT, &event) == 0) {
-              if (event.status & FE_REINIT) {
-                 tunerStatus = tsSet;
-                 esyslog("ERROR: frontend %d was reinitialized - re-tuning", cardIndex);
+           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);
+                    }
+                 if (event.status & FE_HAS_LOCK) {
+                    cMutexLock MutexLock(&mutex);
+                    tunerStatus = tsLocked;
+                    locked.Broadcast();
+                    }
                  }
-              }
            }
         if (ciHandler) {
            if (ciHandler->Process() && useCa) {
@@ -293,7 +306,7 @@
            }
         Unlock();
         // in the beginning we loop more often to let the CAM connection start up fast
-        newSet.Wait((ciHandler && (time(NULL) - startTime < 20)) ? 100 : 1000);
+        newSet.Wait((tunerStatus == tsTuned || ciHandler && (time(NULL) - startTime < 20)) ? 100 : 1000);
         }
 }
 
@@ -746,14 +759,15 @@
   if (TurnOffLivePIDs)
      TurnOffLiveMode();
 
+  // Set the tuner and wait for a lock:
+
   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(TUNER_LOCK_TIMEOUT)) {
+     //XXX esyslog("ERROR: no lock for channel %s on device %d", Channel->ToText(), CardIndex() + 1);
+     return false;
+     }
+
   // PID settings:
 
   if (TurnOnLivePIDs) {

Home | Main Index | Thread Index