]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
dvb: Better handling of uncorrected blocks counter
authorAndreas Öman <andreas@lonelycoder.com>
Tue, 3 May 2011 19:53:21 +0000 (21:53 +0200)
committerAndreas Öman <andreas@lonelycoder.com>
Tue, 3 May 2011 19:53:21 +0000 (21:53 +0200)
Some DVB adapters return delta value from last read. Some return
absolute value since adapter was created.
Add some heuristics that tries to autodetect this.

Ticket #393

src/dvb/dvb.h
src/dvb/dvb_fe.c

index 347fe31a82a3729d380435e73113ee5e3039cfa7..9c14e23f2c087b4b509bcb76f8b51c1ae44b400c 100644 (file)
@@ -200,6 +200,11 @@ typedef struct th_dvb_adapter {
   int tda_allpids_dmx_fd;
   int tda_dump_fd;
 
+  uint32_t tda_last_fec;
+
+  int tda_unc_is_delta;  /* 1 if we believe FE_READ_UNCORRECTED_BLOCKS
+                         * return dela values */
+
 } th_dvb_adapter_t;
 
 
index 2382113489f94c1a44660c7e832f4ef6bb4d0052..9e7b78909329a2cf7ee7021cbcba1adf814fcafd 100644 (file)
 #include "notify.h"
 #include "dvr/dvr.h"
 
+/**
+ * Return uncorrected block (since last read)
+ *
+ * Some adapters report delta themselfs, some return ever increasing value
+ * we need to deal with that ourselfs
+ */
+static int
+dvb_fe_get_unc(th_dvb_adapter_t *tda)
+{
+  uint32_t fec;
+  int d, r;
+
+  if(ioctl(tda->tda_fe_fd, FE_READ_UNCORRECTED_BLOCKS, &fec))
+    return 0; // read failed, just say 0
+
+  if(tda->tda_unc_is_delta)
+    return fec;
+
+  d = (int)fec - (int)tda->tda_last_fec;
+
+  if(d < 0) {
+    tda->tda_unc_is_delta = 1;
+    tvhlog(LOG_DEBUG, "dvb",
+          "%s: FE_READ_UNCORRECTED_BLOCKS returns delta updates (delta=%d)",
+          tda->tda_displayname, d);
+    return fec;
+  }
+  
+  r = fec - tda->tda_last_fec;
+
+  tda->tda_last_fec = fec;
+  return r;
+}
+
+
+
 /**
  * Front end monitor
  *
@@ -79,7 +115,7 @@ dvb_fe_monitor(void *aux)
     if(status == -1) { /* We have a lock, don't hold off */
       tda->tda_fe_monitor_hold = 0; 
       /* Reset FEC counter */
-      ioctl(tda->tda_fe_fd, FE_READ_UNCORRECTED_BLOCKS, &fec);
+      dvb_fe_get_unc(tda);
     } else {
       tda->tda_fe_monitor_hold--;
       return;
@@ -89,8 +125,7 @@ dvb_fe_monitor(void *aux)
   if(status == -1) {
     /* Read FEC counter (delta) */
 
-    if(ioctl(tda->tda_fe_fd, FE_READ_UNCORRECTED_BLOCKS, &fec))
-      fec = 0;
+    fec = dvb_fe_get_unc(tda);
     
     tdmi->tdmi_fec_err_histogram[tdmi->tdmi_fec_err_ptr++] = fec;
     if(tdmi->tdmi_fec_err_ptr == TDMI_FEC_ERR_HISTOGRAM_SIZE)
@@ -277,7 +312,7 @@ static int check_frontend (int fe_fd, int dvr, int human_readable) {
   (void)dvr;
   fe_status_t status;
   uint16_t snr, signal;
-  uint32_t ber, uncorrected_blocks;
+  uint32_t ber;
   int timeout = 0;
 
   do {
@@ -292,15 +327,13 @@ static int check_frontend (int fe_fd, int dvr, int human_readable) {
       snr = -2;
     if (ioctl(fe_fd, FE_READ_BER, &ber) == -1)
       ber = -2;
-    if (ioctl(fe_fd, FE_READ_UNCORRECTED_BLOCKS, &uncorrected_blocks) == -1)
-      uncorrected_blocks = -2;
 
     if (human_readable) {
-      printf ("status %02x | signal %3u%% | snr %3u%% | ber %d | unc %d | ",
-          status, (signal * 100) / 0xffff, (snr * 100) / 0xffff, ber, uncorrected_blocks);
+      printf ("status %02x | signal %3u%% | snr %3u%% | ber %d | ",
+          status, (signal * 100) / 0xffff, (snr * 100) / 0xffff, ber);
     } else {
-      printf ("status %02x | signal %04x | snr %04x | ber %08x | unc %08x | ",
-          status, signal, snr, ber, uncorrected_blocks);
+      printf ("status %02x | signal %04x | snr %04x | ber %08x | ",
+          status, signal, snr, ber);
     }
     if (status & FE_HAS_LOCK)
       printf("FE_HAS_LOCK");