diff --git a/dvb.c b/dvb.c
index 810514f1..3c47985c 100644
--- a/dvb.c
+++ b/dvb.c
@@ -339,6 +339,7 @@ dvb_fec_monitor(void *aux, int64_t now)
{
th_dvb_adapter_t *tda = aux;
th_dvb_mux_instance_t *tdmi;
+ int i, v, vv;
dtimer_arm(&tda->tda_fec_monitor_timer, dvb_fec_monitor, tda, 1);
@@ -346,12 +347,22 @@ dvb_fec_monitor(void *aux, int64_t now)
if(tdmi != NULL && tdmi->tdmi_status == NULL) {
- if(tdmi->tdmi_fec_err_per_sec > DVB_FEC_ERROR_LIMIT) {
+ v = vv = 0;
+ for(i = 0; i < TDMI_FEC_ERR_HISTOGRAM_SIZE; i++) {
+ if(tdmi->tdmi_fec_err_histogram[i] > DVB_FEC_ERROR_LIMIT)
+ v++;
+ vv += tdmi->tdmi_fec_err_histogram[i];
+ }
+ vv /= TDMI_FEC_ERR_HISTOGRAM_SIZE;
+ if(v == TDMI_FEC_ERR_HISTOGRAM_SIZE) {
if(LIST_FIRST(&tda->tda_transports) != NULL) {
- syslog(LOG_ERR, "\"%s\": Too many FEC errors (%d / s), "
- "flushing subscribers\n",
- tdmi->tdmi_uniquename, tdmi->tdmi_fec_err_per_sec);
+ syslog(LOG_ERR,
+ "\"%s\": Constant rate of FEC errors (average at %d / s), "
+ "last %d seconds, flushing subscribers\n",
+ tdmi->tdmi_uniquename, vv,
+ TDMI_FEC_ERR_HISTOGRAM_SIZE);
+
dvb_adapter_clean(tdmi->tdmi_adapter);
}
}
diff --git a/dvb.h b/dvb.h
index 4468dbf0..7d2c3a42 100644
--- a/dvb.h
+++ b/dvb.h
@@ -19,7 +19,7 @@
#ifndef DVB_H_
#define DVB_H_
-#define DVB_FEC_ERROR_LIMIT 10
+#define DVB_FEC_ERROR_LIMIT 20
extern struct th_dvb_adapter_list dvb_adapters_probing;
extern struct th_dvb_adapter_list dvb_adapters_running;
diff --git a/dvb_dvr.c b/dvb_dvr.c
index f36aceeb..c07e15bb 100644
--- a/dvb_dvr.c
+++ b/dvb_dvr.c
@@ -141,7 +141,7 @@ dvb_start_feed(th_transport_t *t, unsigned int weight, int status)
{
struct dmx_pes_filter_params dmx_param;
th_stream_t *st;
- int w, fd, pid;
+ int w, fd, pid, i;
th_dvb_adapter_t *tda = t->tht_dvb_mux_instance->tdmi_adapter;
th_dvb_mux_instance_t *tdmi = tda->tda_mux_current;
@@ -154,8 +154,9 @@ dvb_start_feed(th_transport_t *t, unsigned int weight, int status)
if(tdmi->tdmi_status != NULL)
return 1; /* no lock on adapter, cant use it */
- if(tdmi->tdmi_fec_err_per_sec > DVB_FEC_ERROR_LIMIT / 3)
- return 1; /* too many errors for using it */
+ for(i = 0; i < TDMI_FEC_ERR_HISTOGRAM_SIZE; i++)
+ if(tdmi->tdmi_fec_err_histogram[i] > DVB_FEC_ERROR_LIMIT)
+ return 1; /* too many errors for using it */
w = transport_compute_weight(&tdmi->tdmi_adapter->tda_transports);
if(w > weight)
diff --git a/dvb_fe.c b/dvb_fe.c
index 01bc6eb4..561d551f 100644
--- a/dvb_fe.c
+++ b/dvb_fe.c
@@ -135,8 +135,12 @@ dvb_fe_manager(void *aux)
ioctl(tda->tda_fe_fd, FE_READ_UNCORRECTED_BLOCKS, &v);
- if(fe_status & FE_HAS_LOCK)
- tdmi->tdmi_fec_err_per_sec = (tdmi->tdmi_fec_err_per_sec * 7 + v) / 8;
+ if(fe_status & FE_HAS_LOCK) {
+ tdmi->tdmi_fec_err_histogram[tdmi->tdmi_fec_err_ptr] = v;
+ tdmi->tdmi_fec_err_ptr++;
+ if(tdmi->tdmi_fec_err_ptr == TDMI_FEC_ERR_HISTOGRAM_SIZE)
+ tdmi->tdmi_fec_err_ptr = 0;
+ }
}
}
diff --git a/htmlui.c b/htmlui.c
index 22c2909e..41a43920 100644
--- a/htmlui.c
+++ b/htmlui.c
@@ -1206,6 +1206,7 @@ page_status(http_connection_t *hc, const char *remain, void *opaque)
th_stream_t *st;
const char *txt, *t1, *t2;
char tmptxt[100];
+ int i, v, vv;
if(!html_verify_access(hc, "system-status"))
return HTTP_STATUS_UNAUTHORIZED;
@@ -1250,8 +1251,19 @@ page_status(http_connection_t *hc, const char *remain, void *opaque)
tdmi->tdmi_shortname);
txt = tdmi->tdmi_status ?: "Ok";
- if(tdmi->tdmi_fec_err_per_sec > DVB_FEC_ERROR_LIMIT)
- txt = "Too high FEC rate";
+
+ v = vv = 0;
+ for(i = 0; i < TDMI_FEC_ERR_HISTOGRAM_SIZE; i++) {
+ if(tdmi->tdmi_fec_err_histogram[i] > DVB_FEC_ERROR_LIMIT)
+ v++;
+ vv += tdmi->tdmi_fec_err_histogram[i];
+ }
+ vv /= TDMI_FEC_ERR_HISTOGRAM_SIZE;
+
+ if(v == TDMI_FEC_ERR_HISTOGRAM_SIZE)
+ txt = "Constant high FEC rate";
+ else if(v > 0)
+ txt = "Bursty FEC rate";
tcp_qprintf(&tq,
""
"%d"
"
",
- tdmi->tdmi_fec_err_per_sec);
+ vv);
}
}
}
diff --git a/htsclient.c b/htsclient.c
index 90f803e6..95a070ec 100644
--- a/htsclient.c
+++ b/htsclient.c
@@ -180,7 +180,7 @@ print_tdmi(client_t *c, th_dvb_mux_instance_t *tdmi)
return;
}
- cprintf(c, "locked, %d errors / second\n", tdmi->tdmi_fec_err_per_sec);
+ cprintf(c, "locked\n");
}
/*
diff --git a/tvhead.h b/tvhead.h
index 379d3d59..30cd2a65 100644
--- a/tvhead.h
+++ b/tvhead.h
@@ -155,7 +155,9 @@ typedef struct th_dvb_mux_instance {
uint16_t tdmi_snr, tdmi_signal;
uint32_t tdmi_ber, tdmi_uncorrected_blocks;
- uint32_t tdmi_fec_err_per_sec;
+#define TDMI_FEC_ERR_HISTOGRAM_SIZE 10
+ uint32_t tdmi_fec_err_histogram[TDMI_FEC_ERR_HISTOGRAM_SIZE];
+ int tdmi_fec_err_ptr;
time_t tdmi_time;
LIST_HEAD(, th_dvb_table) tdmi_tables;