From: Jaroslav Kysela Date: Fri, 22 Jun 2018 07:38:50 +0000 (+0200) Subject: eit: add SDT callback, issue #5083 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=26a91d73d8cd397a69ebea4bb5a39dc2978ee129;p=thirdparty%2Ftvheadend.git eit: add SDT callback, issue #5083 --- diff --git a/data/conf/epggrab/eit/config b/data/conf/epggrab/eit/config index 5be540a9b..67ccb975c 100644 --- a/data/conf/epggrab/eit/config +++ b/data/conf/epggrab/eit/config @@ -69,6 +69,7 @@ "Sirius": { "nbid": 85 }, "Viasat": { "nbid": 86 } }, + "pid": 37, "prio": 5 }, @@ -101,7 +102,8 @@ "name": { "eng": "EIT: EPG Grabber" }, - "prio": 1 + "prio": 1, + "sdt_enable": 1 } } diff --git a/src/epggrab.h b/src/epggrab.h index 5967c435a..6fd72e232 100644 --- a/src/epggrab.h +++ b/src/epggrab.h @@ -266,6 +266,11 @@ struct epggrab_ota_map uint8_t om_first; uint8_t om_forced; uint64_t om_tune_count; + enum { + EPGGRAB_OTA_MUX_EIT_IDLE, + EPGGRAB_OTA_MUX_EIT_NIT, + EPGGRAB_OTA_MUX_EIT_SDT + } om_eit_state; RB_HEAD(,epggrab_ota_svc_link) om_svcs; ///< Muxes we carry data for void *om_opaque; }; diff --git a/src/epggrab/module/eit.c b/src/epggrab/module/eit.c index acf3c08e8..3fdd46b0a 100644 --- a/src/epggrab/module/eit.c +++ b/src/epggrab/module/eit.c @@ -44,6 +44,14 @@ typedef struct eit_nit { int nbid_count; } eit_nit_t; +typedef struct eit_sdt { + LIST_ENTRY(eit_sdt) link; + uint16_t onid[32]; + uint16_t tsid[32]; + int onid_count; + int tsid_count; +} eit_sdt_t; + typedef struct eit_private { TAILQ_ENTRY(eit_private) link; @@ -51,9 +59,11 @@ typedef struct eit_private uint16_t pid; uint16_t bat_pid; int conv; + uint32_t sdt_enable; uint32_t hacks; - uint32_t nitpriv; + uint32_t priv; LIST_HEAD(, eit_nit) nit; + LIST_HEAD(, eit_sdt) sdt; epggrab_ota_module_ops_t *ops; } eit_private_t; @@ -1170,22 +1180,70 @@ static int eit_nit_array_check(uint16_t val, uint16_t *array, int array_count) return 1; } -void eit_nit_callback(mpegts_table_t *mt, uint16_t nbid, const char *name, uint32_t nitpriv) +static void eit_install_handlers + (mpegts_mux_t *dm, eit_private_t *priv, const char *src, int state) { - mpegts_mux_t *dm = mt->mt_mux; epggrab_ota_mux_t *om; epggrab_ota_map_t *map; - epggrab_module_ota_t *m = NULL; + epggrab_module_ota_t *m = priv->module; + int pid, opts = 0; + + if (priv->bat_pid) { + mpegts_table_add(dm, DVB_BAT_BASE, DVB_BAT_MASK, dvb_bat_callback, NULL, + "ebat", LS_TBL_BASE, MT_CRC, priv->bat_pid, MPS_WEIGHT_EIT); + } + + om = epggrab_ota_find_mux(dm); + if (!om) + return; + if (state == EPGGRAB_OTA_MUX_EIT_SDT) { + /* check, if NIT EIT is already installed */ + LIST_FOREACH(map, &om->om_modules, om_link) + if (map->om_eit_state == EPGGRAB_OTA_MUX_EIT_NIT) + return; + } + LIST_FOREACH(map, &om->om_modules, om_link) { + if (map->om_module == m) + break; + } + if (!map || (!m->enabled && !map->om_forced)) { + tvhtrace(m->subsys, "%s - module '%s' not enabled", src, m->id); + return; + } + if (map->om_eit_state != EPGGRAB_OTA_MUX_EIT_IDLE) { + tvhtrace(m->subsys, "%s - module '%s' already installed", src, m->id); + return; + } + map->om_eit_state = state; + + tvhtrace(m->subsys, "%s - detected module '%s'", src, m->id); + priv = (eit_private_t *)m->opaque; + pid = priv->pid; + + /* Standard (0x12) */ + if (pid == 0) { + pid = DVB_EIT_PID; + opts = MT_RECORD; + } + + mpegts_table_add(dm, 0, 0, _eit_callback, map, map->om_module->id, LS_TBL_EIT, + MT_CRC | opts, pid, MPS_WEIGHT_EIT); + // TODO: might want to limit recording to EITpf only + tvhdebug(m->subsys, "%s: installed table handlers (%s)", m->id, src); +} + +void eit_nit_callback + (mpegts_table_t *mt, uint16_t nbid, const char *name, uint32_t nitpriv) +{ + mpegts_mux_t *dm = mt->mt_mux; eit_nit_t *nit; eit_private_t *priv = NULL; - int pid, opts = 0; tvhtrace(LS_TBL_EIT, "NIT - tsid %04X (%d) onid %04X (%d) nbid %04X (%d) network name '%s' private %08X", dm->mm_tsid, dm->mm_tsid, dm->mm_onid, dm->mm_onid, nbid, nbid, name, nitpriv); TAILQ_FOREACH(priv, &eit_private_list, link) { - m = priv->module; - if (priv->nitpriv && priv->nitpriv != nitpriv) + if (priv->priv && priv->priv != nitpriv) continue; if (LIST_FIRST(&priv->nit)) { LIST_FOREACH(nit, &priv->nit, link) { @@ -1209,37 +1267,48 @@ void eit_nit_callback(mpegts_table_t *mt, uint16_t nbid, const char *name, uint3 if (!priv) return; - if (priv->bat_pid) { - mpegts_table_add(dm, DVB_BAT_BASE, DVB_BAT_MASK, dvb_bat_callback, NULL, - "ebat", LS_TBL_BASE, MT_CRC, priv->bat_pid, MPS_WEIGHT_EIT); - } + eit_install_handlers(dm, priv, "NIT", EPGGRAB_OTA_MUX_EIT_NIT); +} - om = epggrab_ota_find_mux(dm); - if (!om) - return; - LIST_FOREACH(map, &om->om_modules, om_link) { - if (map->om_module == m) - break; - } - if (!map || (!m->enabled && !map->om_forced)) { - tvhtrace(m->subsys, "NIT - module '%s' not enabled", m->id); +void eit_sdt_callback(mpegts_table_t *mt, uint32_t sdtpriv) +{ + mpegts_mux_t *dm = mt->mt_mux; + eit_sdt_t *sdt; + eit_private_t *priv = NULL; + + /* do not rerun */ + assert(mt->mt_bat == NULL || mt->mt_bat == mt); + if (mt->mt_bat) return; - } + mt->mt_bat = mt; - tvhtrace(m->subsys, "NIT - detected module '%s'", m->id); - priv = (eit_private_t *)m->opaque; - pid = priv->pid; + tvhtrace(LS_TBL_EIT, "SDT - tsid %04X (%d) onid %04X (%d) private %08X", + dm->mm_tsid, dm->mm_tsid, dm->mm_onid, dm->mm_onid, sdtpriv); - /* Standard (0x12) */ - if (pid == 0) { - pid = DVB_EIT_PID; - opts = MT_RECORD; + TAILQ_FOREACH(priv, &eit_private_list, link) { + if (!priv->sdt_enable) + continue; + if (priv->priv && priv->priv != sdtpriv) + continue; + if (LIST_FIRST(&priv->sdt)) { + LIST_FOREACH(sdt, &priv->sdt, link) { + if (eit_nit_array_check(dm->mm_onid, sdt->onid, sdt->onid_count)) + continue; + if (eit_nit_array_check(dm->mm_tsid, sdt->tsid, sdt->tsid_count)) + continue; + break; + } + if (sdt) + break; + } else { + break; + } } - mpegts_table_add(dm, 0, 0, _eit_callback, map, map->om_module->id, LS_TBL_EIT, - MT_CRC | opts, pid, MPS_WEIGHT_EIT); - // TODO: might want to limit recording to EITpf only - tvhdebug(m->subsys, "%s: installed table handlers", m->id); + if (!priv) + return; + + eit_install_handlers(dm, priv, "SDT", EPGGRAB_OTA_MUX_EIT_SDT); } static void _eit_scrape_clear(eit_module_t *mod) @@ -1435,6 +1504,7 @@ static void eit_init_one ( const char *id, htsmsg_t *conf ) epggrab_ota_module_ops_t *ops; eit_private_t *priv; eit_nit_t *nit; + eit_sdt_t *sdt; const char *s; htsmsg_t *map, *e; htsmsg_field_t *f; @@ -1454,7 +1524,7 @@ static void eit_init_one ( const char *id, htsmsg_t *conf ) s = htsmsg_get_str(conf, "conv"); if (s && strcmp(s, "huffman") == 0) priv->conv = EIT_CONV_HUFFMAN; - priv->nitpriv = htsmsg_get_u32_or_default(conf, "priv", 0); + priv->priv = htsmsg_get_u32_or_default(conf, "priv", 0); map = htsmsg_get_map(conf, "nit"); if (map) { HTSMSG_FOREACH(f, map) { @@ -1468,6 +1538,18 @@ static void eit_init_one ( const char *id, htsmsg_t *conf ) LIST_INSERT_HEAD(&priv->nit, nit, link); } } + priv->sdt_enable = htsmsg_get_u32_or_default(conf, "sdt_enable", 0); + map = htsmsg_get_map(conf, "sdt"); + if (map) { + HTSMSG_FOREACH(f, map) { + sdt = calloc(1, sizeof(*sdt)); + if ((e = htsmsg_field_get_map(f)) != NULL) { + eit_parse_list(e, "onid", nit->onid, ARRAY_SIZE(sdt->onid), &sdt->onid_count); + eit_parse_list(e, "tsid", nit->tsid, ARRAY_SIZE(sdt->tsid), &sdt->tsid_count); + } + LIST_INSERT_HEAD(&priv->sdt, sdt, link); + } + } map = htsmsg_get_map(conf, "hacks"); if (map) { HTSMSG_FOREACH(f, map) { diff --git a/src/epggrab/otamux.c b/src/epggrab/otamux.c index 939e13d14..917741974 100644 --- a/src/epggrab/otamux.c +++ b/src/epggrab/otamux.c @@ -280,6 +280,7 @@ epggrab_ota_start ( epggrab_ota_mux_t *om, mpegts_mux_t *mm ) if (modname && !strcmp(modname, map->om_module->id)) map->om_forced = 1; map->om_complete = 0; + map->om_eit_state = EPGGRAB_OTA_MUX_EIT_IDLE; if (map->om_module->start(map, mm) < 0) { map->om_complete = 1; } else diff --git a/src/input/mpegts.h b/src/input/mpegts.h index 6d88db94c..9d29d56ca 100644 --- a/src/input/mpegts.h +++ b/src/input/mpegts.h @@ -266,6 +266,7 @@ struct mpegts_table int mt_destroyed; // Refcounting int mt_arefcount; + uint32_t mt_priv; struct mpegts_table_mux_cb *mt_mux_cb; @@ -1169,6 +1170,7 @@ LIST_HEAD(,mpegts_listener) mpegts_listeners; * misc */ void eit_nit_callback(mpegts_table_t *mt, uint16_t nbid, const char *name, uint32_t priv); +void eit_sdt_callback(mpegts_table_t *mt, uint32_t priv); #endif /* __TVH_MPEGTS_H__ */ diff --git a/src/input/mpegts/dvb_psi.c b/src/input/mpegts/dvb_psi.c index 97d38df16..db27e3ce1 100644 --- a/src/input/mpegts/dvb_psi.c +++ b/src/input/mpegts/dvb_psi.c @@ -1639,6 +1639,7 @@ dvb_sdt_mux case DVB_DESC_PRIVATE_DATA: if (dlen == 4) { priv = extract_4byte(dptr); + if (priv && mt->mt_priv == 0) mt->mt_priv = priv; tvhtrace(mt->mt_subsys, "%s: private %08X", mt->mt_name, priv); } break; @@ -1739,7 +1740,14 @@ dvb_sdt_callback if (tableid != 0x42 && tableid != 0x46) return -1; r = dvb_table_begin((mpegts_psi_table_t *)mt, ptr, len, tableid, extraid, 8, &st, §, &last, &ver, 0); - if (r != 1) return r; + if (r != 1) { + if (r == 0) { + /* install EIT handlers, but later than from optional NIT */ + if (mm->mm_start_monoclock + sec2mono(10) < mclk()) + eit_sdt_callback(mt, mt->mt_priv); + } + return r; + } /* ID */ tvhdebug(mt->mt_subsys, "%s: onid %04X (%d) tsid %04X (%d)", @@ -1756,6 +1764,9 @@ dvb_sdt_callback r = dvb_sdt_mux(mt, mm, mm, ptr, len, tableid); if (r) return r; + /* install EIT handlers, but later than from optional NIT */ + if (mm->mm_start_monoclock + sec2mono(10) < mclk()) + eit_sdt_callback(mt, mt->mt_priv); } else { LIST_FOREACH(mm, &mn->mn_muxes, mm_network_link) if (mm->mm_onid == onid && mm->mm_tsid == tsid && diff --git a/src/input/mpegts/mpegts_table.c b/src/input/mpegts/mpegts_table.c index df40748fb..8049bd14e 100644 --- a/src/input/mpegts/mpegts_table.c +++ b/src/input/mpegts/mpegts_table.c @@ -119,7 +119,7 @@ mpegts_table_release_ ( mpegts_table_t *mt ) tvhtrace(LS_MPEGTS, "table: mux %p free %s %02X/%02X (%d) pid %04X (%d)", mt->mt_mux, mt->mt_name, mt->mt_table, mt->mt_mask, mt->mt_table, mt->mt_pid, mt->mt_pid); - if (mt->mt_bat) + if (mt->mt_bat && mt->mt_bat != mt) dvb_bat_destroy(mt); if (mt->mt_destroy) mt->mt_destroy(mt);