Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
linuxdvb: add nodata and signal retune code
Sometimes, the linux drivers requires "re-tune" requests to stabilize
or re-trigger reception which may hang. The two checks were added:

nodata - when no data are available for a little time period, issue re-tune
signal - when signal is lost for a little time period, issue re-tune
  • Loading branch information
perexg committed Jan 17, 2015
1 parent 93aac31 commit 4df20c2
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 8 deletions.
50 changes: 42 additions & 8 deletions src/input/mpegts/linuxdvb/linuxdvb_frontend.c
Expand Up @@ -33,6 +33,7 @@
#include <linux/dvb/dmx.h>
#include <linux/dvb/frontend.h>

#define NOSIGNAL(x) (((x) & FE_HAS_SIGNAL) == 0)

static void
linuxdvb_frontend_monitor ( void *aux );
Expand Down Expand Up @@ -303,9 +304,10 @@ linuxdvb_frontend_stop_mux
}

/* Not locked */
lfe->lfe_ready = 0;
lfe->lfe_locked = 0;
lfe->lfe_status = 0;
lfe->lfe_ready = 0;
lfe->lfe_locked = 0;
lfe->lfe_status = 0;
lfe->lfe_status2 = 0;

/* Ensure it won't happen immediately */
gtimer_arm(&lfe->lfe_monitor_timer, linuxdvb_frontend_monitor, lfe, 2);
Expand All @@ -314,6 +316,7 @@ linuxdvb_frontend_stop_mux
linuxdvb_satconf_post_stop_mux(lfe->lfe_satconf);

lfe->lfe_in_setup = 0;
lfe->lfe_freq = 0;
}

static int
Expand Down Expand Up @@ -480,7 +483,7 @@ linuxdvb_frontend_monitor ( void *aux )
signal_status_t sigstat;
streaming_message_t sm;
service_t *s;
int logit = 0;
int logit = 0, retune;
#if DVB_VER_ATLEAST(5,10)
struct dtv_property fe_properties[6];
struct dtv_properties dtv_prop;
Expand Down Expand Up @@ -546,8 +549,20 @@ linuxdvb_frontend_monitor ( void *aux )
} else {
tvhtrace("linuxdvb", "%s - status %d (%04X)", buf, status, fe_status);
}
retune = NOSIGNAL(fe_status) && NOSIGNAL(lfe->lfe_status) && !NOSIGNAL(lfe->lfe_status2);
lfe->lfe_status2 = lfe->lfe_status;
lfe->lfe_status = fe_status;

/* Retune check - we lost signal or no data were received */
if (retune || lfe->lfe_nodata) {
lfe->lfe_nodata = 0;
if (lfe->lfe_freq > 0) {
tvhlog(LOG_WARNING, "linuxdvb", "%s - %s", buf, retune ? "retune" : "retune nodata");
linuxdvb_frontend_tune0(lfe, mmi, lfe->lfe_freq);
gtimer_arm_ms(&lfe->lfe_monitor_timer, linuxdvb_frontend_monitor, lfe, 50);
}
}

/* Get current mux */
mm = mmi->mmi_mux;

Expand Down Expand Up @@ -586,6 +601,11 @@ linuxdvb_frontend_monitor ( void *aux )
return;
lfe->lfe_monitor = dispatch_clock + 1;
}
} else {
/* Monitor 1 per sec */
if (dispatch_clock < lfe->lfe_monitor)
return;
lfe->lfe_monitor = dispatch_clock + 1;
}

/* Statistics - New API */
Expand Down Expand Up @@ -839,6 +859,7 @@ linuxdvb_frontend_input_thread ( void *aux )
size_t skip = (MIN(lfe->lfe_skip_bytes, 1024*1024) / 188) * 188;
size_t counter = 0;
sbuf_t sb;
int nodata = 8;

/* Get MMI */
pthread_mutex_lock(&lfe->lfe_dvr_lock);
Expand Down Expand Up @@ -869,9 +890,21 @@ linuxdvb_frontend_input_thread ( void *aux )

/* Read */
while (tvheadend_running) {
nfds = tvhpoll_wait(efd, ev, 1, -1);
nfds = tvhpoll_wait(efd, ev, 1, 15);
if (nfds == 0) { /* timeout */
if (nodata == 0) {
tvhlog(LOG_WARNING, "linuxdvb", "%s - poll TIMEOUT", buf);
nodata = 50;
lfe->lfe_nodata = 1;
} else {
nodata--;
}
}
if (nfds < 1) continue;
if (ev[0].data.fd != dvr) break;

nodata = 50;
lfe->lfe_nodata = 0;

/* Read */
if ((n = sbuf_tsdebug_read(mmi->mmi_mux, &sb, dvr)) < 0) {
Expand Down Expand Up @@ -1002,8 +1035,9 @@ linuxdvb_frontend_clear
return SM_CODE_TUNING_FAILED;
}
}
lfe->lfe_locked = 0;
lfe->lfe_status = 0;
lfe->lfe_locked = 0;
lfe->lfe_status = 0;
lfe->lfe_status2 = 0;

#if DVB_API_VERSION >= 5
static struct dtv_property clear_p[] = {
Expand Down Expand Up @@ -1206,7 +1240,7 @@ linuxdvb_frontend_tune0
}

if (freq != (uint32_t)-1)
p.frequency = freq;
p.frequency = lfe->lfe_freq = freq;

if (dmc->dmc_fe_type != lfe->lfe_type) {
tvherror("linuxdvb", "%s - failed to tune [type does not match %i != %i]", buf1, dmc->dmc_fe_type, lfe->lfe_type);
Expand Down
3 changes: 3 additions & 0 deletions src/input/mpegts/linuxdvb/linuxdvb_private.h
Expand Up @@ -102,7 +102,10 @@ struct linuxdvb_frontend
int lfe_in_setup;
int lfe_locked;
int lfe_status;
int lfe_status2;
int lfe_ioctls;
int lfe_nodata;
int lfe_freq;
time_t lfe_monitor;
gtimer_t lfe_monitor_timer;
tvhlog_limit_t lfe_status_log;
Expand Down

0 comments on commit 4df20c2

Please sign in to comment.