]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
eit: add SDT callback, issue #5083
authorJaroslav Kysela <perex@perex.cz>
Fri, 22 Jun 2018 07:38:50 +0000 (09:38 +0200)
committerJaroslav Kysela <perex@perex.cz>
Fri, 22 Jun 2018 08:08:06 +0000 (10:08 +0200)
data/conf/epggrab/eit/config
src/epggrab.h
src/epggrab/module/eit.c
src/epggrab/otamux.c
src/input/mpegts.h
src/input/mpegts/dvb_psi.c
src/input/mpegts/mpegts_table.c

index 5be540a9b7d8e6c23d34519a7814a36571b4005c..67ccb975cf1dc8ccda6c409686320ee13ed85442 100644 (file)
@@ -69,6 +69,7 @@
       "Sirius": { "nbid": 85 },
       "Viasat": { "nbid": 86 }
     },
+    "pid": 37,
     "prio": 5
   },
 
     "name": {
       "eng": "EIT: EPG Grabber"
     },
-    "prio": 1
+    "prio": 1,
+    "sdt_enable": 1
   }
 
 }
index 5967c435aac7e58b5d8fc8553da245a64a18e6cd..6fd72e232c208d67389460063c872ef142708575 100644 (file)
@@ -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;
 };
index acf3c08e8d2d3466131e2e8fd9962c9c25caa26e..3fdd46b0aef2f29c60791046ebfcb5e42b356d24 100644 (file)
@@ -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) {
index 939e13d147e9adbed9e3a330b68626b5e12ae28f..917741974eeae3b4f3b0a5219843fa86b47f684d 100644 (file)
@@ -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
index 6d88db94cf6bd25b0d863833a8674062d6f76d75..9d29d56ca270db6e91a7472c77ff8ccd57cc4dd5 100644 (file)
@@ -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__ */
 
index 97d38df16656ae98d9a637d7a40371da9ec63213..db27e3ce19044fe16a9c1501d7b6081094302c8a 100644 (file)
@@ -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, &sect, &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 &&
index df40748fb6821443f1a0802bb446ebed75178832..8049bd14eb306157a1376d8e20e4a03afd711020 100644 (file)
@@ -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);