Mailing List archive

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

[vdr] Re: Fixed tuner lock detection



Klaus Schmidinger wrote:
> 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) {

Question 1: Are you sure the drivers always signal a valid lock on the
first "rising edge" of FE_HAS_LOCK? They didn't in the past (the "spike
problem").

Question 2: How is the case of a loss of lock handled (May occur e.g. in
bad weather conditions?). This case is not handled in
DvbTuner::Action(). Do we get a VDSB error and an emergency exit?

> +                    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;
> +     }
> +

Fine! I am using a similar patch since quite some time now without problems.

>    // PID settings:
>  
>    if (TurnOnLivePIDs) {






Home | Main Index | Thread Index