Mailing List archive

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

[vdr] Re: [PATCH] cDvbTuner



Stefan Meyknecht wrote:
> Hi,
> 
> inspired from szap I have made some changes to cDvbTuner:
> 
> - use WAIT_FOR_LOCK_AFTER_TUNING=1
> 
> - discard stale frontend events before FE_SET_FRONTEND
> 
> - use frontend event to detect if tuner is locked
> 
I think this is not enough. The original logic to detect lock seems to be flawed.
It signals lock after the shortest FE_HAS_LOCK spike. I modified the loop to
use poll() in order to get the frontend events asynchronouslly and instrumented
the loop with some debug code which prints each event to syslog with ms resolution
timing information and found FE_HAS_LOCK events as short as 100 ms. (See
the syslog snippet below). I am now using a modified loop which reqires
to have the FE_HAS_LOCK state for at least 300ms, which removes the
false lock indication for me. Don't know up to know if it really improves things.

I dont't know why the driver delivers such FE_HAS_LOCK spikes. Seems
to be a bug. I'll ask on the DVB mailing list.

Attached my modified cDvbTuner::Action() to this mail. It's quite messed
up and maybe not fully correct, but you get the idea...

Wolfgang

Syslog output:

Jul 25 20:34:27 vdr vdr[4099]: SetChannelDevice: channel 585, LiveView=0
Jul 25 20:34:28 vdr vdr[4099]: Frontend 1 tuning to channel Free-X TV
Jul 25 20:34:28 vdr vdr[4125]: Event on frontend 1 (channel Free-X TV): 00 (#1) dt = 22230 ms
Jul 25 20:34:28 vdr vdr[4125]: Event on frontend 1 (channel Free-X TV): 1f (#2) dt =    0 ms
Jul 25 20:34:28 vdr vdr[4125]: Frontend 1 (channel Free-X TV) locked
Jul 25 20:34:28 vdr vdr[4099]: SetChannelDevice: Channel should be locked
Jul 25 20:34:28 vdr vdr[4125]: Event on frontend 1 (channel Free-X TV): 00 (#1) dt =  100 ms
Jul 25 20:34:28 vdr vdr[4125]: Event on frontend 1 (channel Free-X TV): 02 (#1) dt =  200 ms
Jul 25 20:34:28 vdr vdr[4125]: Event on frontend 1 (channel Free-X TV): 00 (#1) dt =  100 ms
Jul 25 20:34:29 vdr vdr[4125]: Event on frontend 1 (channel Free-X TV): 02 (#1) dt =  800 ms
Jul 25 20:34:29 vdr vdr[4125]: Event on frontend 1 (channel Free-X TV): 00 (#1) dt =  100 ms
Jul 25 20:34:30 vdr vdr[4125]: Event on frontend 1 (channel Free-X TV): 02 (#1) dt =  500 ms
Jul 25 20:34:30 vdr vdr[4125]: Event on frontend 1 (channel Free-X TV): 00 (#1) dt =  200 ms
Jul 25 20:34:30 vdr vdr[4125]: Event on frontend 1 (channel Free-X TV): 02 (#1) dt =  100 ms
Jul 25 20:34:31 vdr vdr[4125]: Event on frontend 1 (channel Free-X TV): 03 (#1) dt =  900 ms
Jul 25 20:34:32 vdr vdr[4125]: Event on frontend 1 (channel Free-X TV): 00 (#1) dt = 1040 ms
Jul 25 20:34:33 vdr vdr[4125]: Event on frontend 1 (channel Free-X TV): 02 (#1) dt = 1290 ms
Jul 25 20:34:33 vdr vdr[4125]: Event on frontend 1 (channel Free-X TV): 00 (#1) dt =  370 ms
Jul 25 20:34:37 vdr vdr[4125]: Event on frontend 1 (channel Free-X TV): 02 (#1) dt = 3760 ms
Jul 25 20:34:39 vdr vdr[4125]: Event on frontend 1 (channel Free-X TV): 00 (#1) dt = 1700 ms
Jul 25 20:34:41 vdr vdr[4125]: Event on frontend 1 (channel Free-X TV): 02 (#1) dt = 1860 ms
Jul 25 20:34:43 vdr vdr[4125]: Event on frontend 1 (channel Free-X TV): 00 (#1) dt = 1970 ms
Jul 25 20:34:45 vdr vdr[4125]: Event on frontend 1 (channel Free-X TV): 02 (#1) dt = 2050 ms
Jul 25 20:34:47 vdr vdr[4125]: Event on frontend 1 (channel Free-X TV): 00 (#1) dt = 2110 ms
Jul 25 20:34:49 vdr vdr[4125]: Event on frontend 1 (channel Free-X TV): 02 (#1) dt = 2180 ms

[cut]


;; This buffer is for notes you don't want to save, and for Lisp evaluation.
;; If you want to create a file, visit that file with C-x C-f,
;; then enter the text in that file's own buffer.

void cDvbTuner::Action(void)
{
  active = true;
  int last;
  last = time_ms ();
  int lockcount = 0;

  while (active) {
        cMutexLock MutexLock(&mutex);
        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;
	      dsyslog ("Frontend %d (channel %s) locked", cardIndex, channel.Name());
	      }
           }
	*/
        bool fast = (tunerStatus == tsTuned) || (ciHandler && (time(NULL) - startTime < 20));
        if (tunerStatus != tsIdle) 
	  {
	    dvb_frontend_event event;
	    struct pollfd pd;
	    pd.fd = fd_frontend;
	    pd.events = POLLIN | POLLPRI;
	    int pr;
	    /* poll call */
	    pr = poll (&pd, 1, fast ? 100 : 1000);
	    if (pr == 1)
	      {
		int count = 0;
		while (ioctl(fd_frontend, FE_GET_EVENT, &event) == 0) 
		  {
		    int now = time_ms ();
		    dsyslog ("Event on frontend %d (channel %s): %02x (#%d) dt =%8d ms", 
			     cardIndex, channel.Name(), event.status, ++count, now - last);
		    last = now;
		    if (event.status & FE_REINIT) 
		      {
			tunerStatus = tsSet;
			esyslog("ERROR: frontend %d was reinitialized - re-tuning", cardIndex);
			continue;
		      }
		    if (event.status & FE_HAS_LOCK) 
		      {
			//tunerStatus = tsLocked;
			dsyslog ("Frontend %d (channel %s) first lock", cardIndex, channel.Name());
		      }
		    lockcount = 0;
		  }
	      } 
	    else 
	      {
		if (pr == 0) 
		  {
		    //dsyslog ("Frontend %d (channel %s) poll timeout", cardIndex, channel.Name());
		    fe_status_t status = fe_status_t(0);
		    CHECK(ioctl(fd_frontend, FE_READ_STATUS, &status));
		    int now = time_ms ();
		    if (status & FE_HAS_LOCK) 
		      {
			if (tunerStatus != tsLocked)
			  {
			    lockcount++;
			    if (lockcount == 3) 
			      {
				dsyslog ("Frontend %d (channel %s) locked after %d ms ", 
					 cardIndex, channel.Name(), now - last);
				last = now;
				tunerStatus = tsLocked;
			      }
			  }
		      }
		    else
		      {
			lockcount = 0; /* should be handled by event */
		      }
		  }
		else 
		  {
		    dsyslog ("Frontend %d (channel %s) poll error (pr=%d)", cardIndex, channel.Name(), pr);
		  }
	      }
	  }
	if (ciHandler) {
	      if (ciHandler->Process() && useCa) {
              if (tunerStatus == tsLocked) {
                 for (int Slot = 0; Slot < ciHandler->NumSlots(); Slot++) {
                     cCiCaPmt CaPmt(channel.Source(), channel.Transponder(), channel.Sid(), ciHandler->GetCaSystemIds(Slot));
                     if (CaPmt.Valid()) {
                        CaPmt.AddPid(channel.Vpid(), 2);
                        CaPmt.AddPid(channel.Apid1(), 4);
                        CaPmt.AddPid(channel.Apid2(), 4);
                        CaPmt.AddPid(channel.Dpid1(), 0);
                        if (ciHandler->SetCaPmt(CaPmt, Slot)) {
                           tunerStatus = tsCam;
                           startTime = 0;
                           }
                        }
                     }
                 }
              }
           else if (tunerStatus > tsLocked)
              tunerStatus = tsLocked;
           }
        // in the beginning we loop more often to let the CAM connection start up fast
        //bool fast = (tunerStatus == tsTuned) || (ciHandler && (time(NULL) - startTime < 20));
        //newSet.TimedWait(mutex, fast ? 100 : 1000);
        }
}


Home | Main Index | Thread Index