diff --git a/dvb.c b/dvb.c index 8a8199ee..9cf93f17 100644 --- a/dvb.c +++ b/dvb.c @@ -320,7 +320,23 @@ dvb_mux_scanner(void *aux, int64_t now) if(transport_compute_weight(&tda->tda_transports) > 0) return; /* someone is here */ + /* Check if we have muxes pending for quickscan, if so, choose them */ + LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) + if(tdmi->tdmi_quickscan == TDMI_QUICKSCAN_WAITING) + break; + + if(tdmi != NULL) { + tdmi->tdmi_quickscan = TDMI_QUICKSCAN_RUNNING; + dvb_tune_tdmi(tdmi, 0, TDMI_IDLESCAN); + return; + } + + /* otherwise, just rotate */ + tdmi = tda->tda_mux_current; + if(tdmi != NULL) + tdmi->tdmi_quickscan = TDMI_QUICKSCAN_NONE; + tdmi = tdmi != NULL ? LIST_NEXT(tdmi, tdmi_adapter_link) : NULL; tdmi = tdmi != NULL ? tdmi : LIST_FIRST(&tda->tda_muxes); @@ -359,6 +375,7 @@ dvb_mux_create(th_dvb_adapter_t *tda, struct dvb_frontend_parameters *fe_param, } tdmi = calloc(1, sizeof(th_dvb_mux_instance_t)); + tdmi->tdmi_quickscan = TDMI_QUICKSCAN_WAITING; tdmi->tdmi_refcnt = 1; pthread_mutex_init(&tdmi->tdmi_table_lock, NULL); tdmi->tdmi_state = TDMI_IDLE; @@ -799,3 +816,29 @@ dvb_tda_destroy(th_dvb_adapter_t *tda) return 0; } + +/** + * + */ +void +dvb_tdmi_fastswitch(th_dvb_mux_instance_t *tdmi) +{ + th_dvb_table_t *tdt; + + if(tdmi->tdmi_quickscan == TDMI_QUICKSCAN_NONE) + return; + + pthread_mutex_lock(&tdmi->tdmi_table_lock); + LIST_FOREACH(tdt, &tdmi->tdmi_tables, tdt_link) { + if(tdt->tdt_quickreq && tdt->tdt_count == 0) + break; + } + pthread_mutex_unlock(&tdmi->tdmi_table_lock); + + if(tdt != NULL) + return; /* Still tables we've not seen */ + + tdmi->tdmi_quickscan = TDMI_QUICKSCAN_NONE; + dvb_mux_scanner(tdmi->tdmi_adapter, 0); + +} diff --git a/dvb.h b/dvb.h index 0c6dc046..a0301af5 100644 --- a/dvb.h +++ b/dvb.h @@ -75,4 +75,6 @@ void dvb_tda_clone(th_dvb_adapter_t *dst, th_dvb_adapter_t *src); int dvb_tda_destroy(th_dvb_adapter_t *tda); +void dvb_tdmi_fastswitch(th_dvb_mux_instance_t *tdmi); + #endif /* DVB_H_ */ diff --git a/dvb_tables.c b/dvb_tables.c index f979cdb5..c635ca0f 100644 --- a/dvb_tables.c +++ b/dvb_tables.c @@ -44,6 +44,7 @@ #include "notify.h" #define TDT_NOW 0x1 +#define TDT_QUICKREQ 0x2 /** * @@ -93,7 +94,10 @@ dvb_table_recv(int events, void *opaque, int fd) ptr = &sec[3]; len -= 4; /* Strip trailing CRC */ + tdt->tdt_count++; + tdt->tdt_callback(tdt->tdt_tdmi, ptr, len, tableid, tdt->tdt_opaque); + dvb_tdmi_fastswitch(tdt->tdt_tdmi); } @@ -124,6 +128,8 @@ tdt_add(th_dvb_mux_instance_t *tdmi, struct dmx_sct_filter_params *fparams, tdt->tdt_tdmi = tdmi; tdt->tdt_handle = dispatch_addfd(fd, dvb_table_recv, tdt, DISPATCH_READ); + tdt->tdt_quickreq = flags & TDT_QUICKREQ ? 1 : 0; + if(flags & TDT_NOW) { ioctl(fd, DMX_SET_FILTER, fparams); free(fparams); @@ -466,8 +472,9 @@ dvb_pat_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, if(service != 0) { t = dvb_find_transport(tdmi, service, pmt, &created); - if(created) /* Add PMT to our table scanner */ + if(created) { /* Add PMT to our table scanner */ dvb_table_add_transport(tdmi, t, pmt); + } } ptr += 4; len -= 4; @@ -758,7 +765,7 @@ dvb_table_add_default(th_dvb_mux_instance_t *tdmi) fp = dvb_fparams_alloc(0x0, DMX_IMMEDIATE_START | DMX_CHECK_CRC); fp->filter.filter[0] = 0x00; fp->filter.mask[0] = 0xff; - tdt_add(tdmi, fp, dvb_pat_callback, NULL, "pat", 0); + tdt_add(tdmi, fp, dvb_pat_callback, NULL, "pat", TDT_QUICKREQ); /* Conditional Access Table */ @@ -770,14 +777,14 @@ dvb_table_add_default(th_dvb_mux_instance_t *tdmi) /* Network Information Table */ fp = dvb_fparams_alloc(0x10, DMX_IMMEDIATE_START | DMX_CHECK_CRC); - tdt_add(tdmi, fp, dvb_nit_callback, NULL, "nit", 0); + tdt_add(tdmi, fp, dvb_nit_callback, NULL, "nit", TDT_QUICKREQ); /* Service Descriptor Table */ fp = dvb_fparams_alloc(0x11, DMX_IMMEDIATE_START | DMX_CHECK_CRC); fp->filter.filter[0] = 0x42; fp->filter.mask[0] = 0xff; - tdt_add(tdmi, fp, dvb_sdt_callback, NULL, "sdt", 0); + tdt_add(tdmi, fp, dvb_sdt_callback, NULL, "sdt", TDT_QUICKREQ); /* Event Information table */ @@ -810,5 +817,5 @@ dvb_table_add_transport(th_dvb_mux_instance_t *tdmi, th_transport_t *t, fp = dvb_fparams_alloc(pmt_pid, DMX_IMMEDIATE_START | DMX_CHECK_CRC); fp->filter.filter[0] = 0x02; fp->filter.mask[0] = 0xff; - tdt_add(tdmi, fp, dvb_pmt_callback, t, pmtname, TDT_NOW); + tdt_add(tdmi, fp, dvb_pmt_callback, t, pmtname, TDT_NOW | TDT_QUICKREQ); } diff --git a/tvhead.h b/tvhead.h index cab9897c..0b653205 100644 --- a/tvhead.h +++ b/tvhead.h @@ -149,6 +149,12 @@ typedef enum { typedef struct th_dvb_mux_instance { int tdmi_refcnt; + enum { + TDMI_QUICKSCAN_NONE, + TDMI_QUICKSCAN_RUNNING, + TDMI_QUICKSCAN_WAITING, + } tdmi_quickscan; + LIST_ENTRY(th_dvb_mux_instance) tdmi_global_link; LIST_ENTRY(th_dvb_mux_instance) tdmi_adapter_link; @@ -205,6 +211,10 @@ typedef struct th_dvb_table { int tdt_fd; struct dmx_sct_filter_params *tdt_fparams; + + int tdt_quickreq; + int tdt_count; + } th_dvb_table_t;