diff --git a/src/epggrab/module/eit.c b/src/epggrab/module/eit.c index b75713ca..3eb99b29 100644 --- a/src/epggrab/module/eit.c +++ b/src/epggrab/module/eit.c @@ -17,6 +17,7 @@ */ #include + #include "tvheadend.h" #include "channels.h" #include "dvb/dvb.h" @@ -32,11 +33,61 @@ typedef struct eit_status { - int tid; - int tsid; - int sid; - int sec; + LIST_ENTRY(eit_status) link; + int tid; + uint16_t tsid; + uint16_t sid; + uint32_t sec[8]; + int done; } eit_status_t; +typedef LIST_HEAD(, eit_status) eit_status_list_t; + +static eit_status_t *eit_status_find + ( eit_status_list_t *el, int tableid, uint16_t tsid, uint16_t sid, + uint8_t sec, uint8_t lst, uint8_t seg ) +{ + int i; + uint32_t msk; + eit_status_t *sta; + + /* Find */ + LIST_FOREACH(sta, el, link) + if (sta->tid == tableid && sta->tsid == tsid && sta->sid == sid) + break; + + /* Already complete */ + if (sta && sta->done) return NULL; + + /* Insert new entry */ + if (!sta) { + sta = calloc(1, sizeof(eit_status_t)); + LIST_INSERT_HEAD(el, sta, link); + sta->tid = tableid; + sta->tsid = tsid; + sta->sid = sid; + for (i = 0; i < (lst / 32); i++) + sta->sec[i] = 0xFFFFFFFF; + if (lst % 32) + sta->sec[i] = (0xFFFFFFFF >> (31-(lst%32))); + } + + /* Get section mask */ + if (sec == seg) { + msk = 0xFF << (((sec/8)%4) * 8); + } else { + msk = 0x1 << (sec%32); + } + + /* Already seen */ + if (!(sta->sec[sec/32] & msk)) return NULL; + + /* Update */ + sta->sec[sec/32] &= ~msk; + sta->done = 1; + for (i = 0; i < 8; i++ ) + if (sta->sec[i]) sta->done = 0; + return sta; +} typedef struct eit_event { @@ -352,6 +403,7 @@ static int _eit_process_event /* Find broadcast */ ebc = epg_broadcast_find_by_time(svc->s_ch, start, stop, eid, 1, &save2); + tvhlog(LOG_DEBUG, mod->id, "eid=%5d, start=%lu, stop=%lu, ebc=%p", eid, start, stop, ebc); if (!ebc) return dllen + 12; /* Mark re-schedule detect (only now/next) */ @@ -463,18 +515,21 @@ static int _eit_callback epggrab_ota_mux_t *ota; th_dvb_adapter_t *tda; service_t *svc; + eit_status_list_t *stal; eit_status_t *sta; int resched = 0, save = 0; uint16_t tsid, sid; /* Invalid */ - if(tableid < 0x4e || tableid > 0x6f || len < 11) - return -1; + if(tableid < 0x4e || tableid > 0x6f || len < 11) return -1; + + /* Don't process */ + if((ptr[2] & 1) == 0) return 0; /* Get OTA */ ota = epggrab_ota_find((epggrab_module_ota_t*)mod, tdmi); if (!ota || !ota->status) return -1; - sta = ota->status; + stal = ota->status; /* Already complete */ if (epggrab_ota_is_complete(ota)) return 0; @@ -483,25 +538,6 @@ static int _eit_callback sid = ptr[0] << 8 | ptr[1]; tsid = ptr[5] << 8 | ptr[6]; - /* Started */ - if (epggrab_ota_begin(ota)) { - sta->tid = tableid; - sta->tsid = tsid; - sta->sid = sid; - sta->sec = ptr[3]; - - /* Complete */ - } else if (sta->tid == tableid && - sta->sec == ptr[3] && - sta->tsid == tsid && - sta->sid == sid) { - epggrab_ota_complete(ota); - return 0; - } - - /* Don't process */ - if((ptr[2] & 1) == 0) return 0; - /* Get transport stream */ // Note: tableid=0x4f,0x60-0x6f is other TS // so must find the tdmi @@ -520,6 +556,20 @@ static int _eit_callback /* Ignore (not primary EPG service) */ if (!service_is_primary_epg(svc)) return 0; + sta = eit_status_find(stal, tableid, tsid, sid, ptr[3], ptr[4], + ptr[9]); + if (!sta) return 0; + + /* Started */ + if (epggrab_ota_begin(ota)) { + // nothing/clear? + + /* Check end */ + } else if (sta->done) { + LIST_FOREACH(sta, stal, link) + if (!sta->done) break; + } + /* Register as interesting */ if (tableid < 0x50) epggrab_ota_register(ota, 20, 300); // 20s grab, 5min interval @@ -528,13 +578,6 @@ static int _eit_callback // Note: this does mean you will get a slight oddity for muxes that // carry both, since they will end up with setting of 600/300 - /* Up to date */ -#if TODO_INCLUDE_EIT_VER_CHECK - ver = ptr[2] >> 1 & 0x1f; - if (svc->s_dvb_eit_version[tableid-0x4f] == ver) return 0; - svc->s_dvb_eit_version[tableid-0x4e] = ver; -#endif - /* Process events */ len -= 11; ptr += 11; @@ -546,6 +589,9 @@ static int _eit_callback len -= r; ptr += r; } + + /* Complete */ + if (!sta) epggrab_ota_complete(ota); /* Update EPG */ if (resched) epggrab_resched(); @@ -558,19 +604,39 @@ static int _eit_callback * Module Setup * ***********************************************************************/ +static void _eit_ota_destroy ( epggrab_ota_mux_t *ota ) +{ + eit_status_t *sta; + eit_status_list_t *stal = ota->status; + + /* Remove all entries */ + while ((sta = LIST_FIRST(stal))) { + LIST_REMOVE(sta, link); + free(sta); + } + + free(stal); + free(ota); +} + static void _eit_start ( epggrab_module_ota_t *m, th_dvb_mux_instance_t *tdmi ) { epggrab_ota_mux_t *ota; if (!m->enabled) return; if (!(ota = epggrab_ota_create(m, tdmi))) return; - if (!ota->status) - ota->status = calloc(1, sizeof(eit_status_t)); - if (!strcmp("freesat", m->id)) - tdt_add(tdmi, NULL, _eit_callback, m, m->id, TDT_CRC, 0xf02, NULL); - else + if (!ota->status) { + ota->status = calloc(1, sizeof(eit_status_list_t)); + ota->destroy = _eit_ota_destroy; + } + if (!strcmp("freesat", m->id)) { +#ifdef IGNORE_TOO_SLOW + tdt_add(tdmi, NULL, _eit_callback, m, m->id, TDT_CRC, 3841, NULL); +#endif + tdt_add(tdmi, NULL, _eit_callback, m, m->id, TDT_CRC, 3003, NULL); + } else tdt_add(tdmi, NULL, _eit_callback, m, m->id, TDT_CRC, 0x12, NULL); - tvhlog(LOG_DEBUG, m->id, "install table handlers"); + tvhlog(LOG_INFO, m->id, "install table handlers"); } static int _eit_enable ( void *m, uint8_t e ) @@ -583,9 +649,14 @@ static int _eit_enable ( void *m, uint8_t e ) /* Register interest */ if (e) { if (!strcmp(mod->id, "freesat")) +#ifdef IGNORE_TOO_SLOW epggrab_ota_create_and_register_by_id((epggrab_module_ota_t*)mod, 0, 2050, - 600, 3600); + 600, 3600, "ASTRA"); +#endif + epggrab_ota_create_and_register_by_id((epggrab_module_ota_t*)mod, + 0, 2315, + 600, 3600, "Freesat"); /* Remove all links */ } else { epggrab_ota_destroy_by_module((epggrab_module_ota_t*)mod);