]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
epggrab: eit - reimplement the EIT grabber selection
authorJaroslav Kysela <perex@perex.cz>
Thu, 13 Sep 2018 15:04:57 +0000 (17:04 +0200)
committerJaroslav Kysela <perex@perex.cz>
Thu, 13 Sep 2018 15:04:57 +0000 (17:04 +0200)
src/epggrab.h
src/epggrab/module.c
src/epggrab/module/eit.c
src/epggrab/otamux.c
src/epggrab/private.h

index 6fd72e232c208d67389460063c872ef142708575..60d84994d53e256e4018c19e0895043edd1d2b24 100644 (file)
@@ -34,6 +34,7 @@ typedef struct epggrab_module_ext   epggrab_module_ext_t;
 typedef struct epggrab_module_ota   epggrab_module_ota_t;
 typedef struct epggrab_module_ota_scraper   epggrab_module_ota_scraper_t;
 typedef struct epggrab_ota_mux      epggrab_ota_mux_t;
+typedef struct epggrab_ota_mux_eit_plist    epggrab_ota_mux_eit_plist_t;
 typedef struct epggrab_ota_map      epggrab_ota_map_t;
 typedef struct epggrab_ota_svc_link epggrab_ota_svc_link_t;
 
@@ -226,6 +227,12 @@ struct epggrab_ota_svc_link
   RB_ENTRY(epggrab_ota_svc_link) link;
 };
 
+struct epggrab_ota_mux_eit_plist {
+  LIST_ENTRY(epggrab_ota_mux_eit_plist) link;
+  const char *src;
+  void *priv;
+};
+
 /*
  * TODO: this could be embedded in the mux itself, but by using a soft-link
  *       and keeping it here I can somewhat isolate it from the mpegts code
@@ -253,6 +260,9 @@ struct epggrab_ota_mux
 
   TAILQ_ENTRY(epggrab_ota_mux)       om_q_link;
   RB_ENTRY(epggrab_ota_mux)          om_global_link;
+
+  LIST_HEAD(, epggrab_ota_mux_eit_plist) om_eit_plist;
+  mtimer_t                           om_eit_timer;
 };
 
 /*
@@ -266,11 +276,6 @@ 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;
 };
@@ -284,6 +289,7 @@ struct epggrab_module_ota
 
   /* Transponder tuning */
   int  (*start) ( epggrab_ota_map_t *map, struct mpegts_mux *mm );
+  int  (*stop)  ( epggrab_ota_map_t *map, struct mpegts_mux *mm );
   int  (*tune)  ( epggrab_ota_map_t *map, epggrab_ota_mux_t *om,
                   struct mpegts_mux *mm );
   void  *opaque;
index aac9884cfde002d271e8d7253806cb9ca8dceb14..faf29dd3c39b6d2e45ca55d617b1c6b83c0dcb3d 100644 (file)
@@ -727,6 +727,7 @@ epggrab_module_ota_t *epggrab_module_ota_create
   skel->type         = EPGGRAB_OTA;
   skel->activate     = ops->activate;
   skel->start        = ops->start;
+  skel->stop         = ops->stop;
   skel->done         = ops->done;
   skel->tune         = ops->tune;
   skel->process_data = ops->process_data;
index e76f15e4ca48ad0bbde2c8ede4da6f6de4b5928e..39953c7b10d37c56258f3892a4d6dcc3de8c22eb 100644 (file)
@@ -103,6 +103,8 @@ typedef struct eit_module_t
 
 static TAILQ_HEAD(, eit_private) eit_private_list;
 
+static void eit_install_handlers(void *aux);
+
 /* ************************************************************************
  * Status handling
  * ***********************************************************************/
@@ -1102,10 +1104,28 @@ static int _eit_start
   ( epggrab_ota_map_t *map, mpegts_mux_t *dm )
 {
   epggrab_module_ota_t *m = map->om_module;
+  epggrab_ota_mux_t *om;
 
   /* Disabled */
   if (!m->enabled && !map->om_forced) return -1;
 
+  om = epggrab_ota_find_mux(dm);
+  if (!om) return -1;
+
+  mtimer_arm_rel(&om->om_eit_timer, eit_install_handlers, dm, sec2mono(20));
+  return 0;
+}
+
+static int _eit_stop
+  ( epggrab_ota_map_t *map, mpegts_mux_t *dm )
+{
+  epggrab_ota_mux_t *om;
+
+  om = epggrab_ota_find_mux(dm);
+  if (!om) return -1;
+
+  mtimer_disarm(&om->om_eit_timer);
+
   return 0;
 }
 
@@ -1180,45 +1200,48 @@ static int eit_nit_array_check(uint16_t val, uint16_t *array, int array_count)
   return 1;
 }
 
-static void eit_install_handlers
-  (mpegts_mux_t *dm, eit_private_t *priv, const char *src, int state)
+static void eit_install_handlers(void *aux)
 {
+  mpegts_mux_t *dm = aux;
   epggrab_ota_mux_t *om;
   epggrab_ota_map_t *map;
-  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);
-  }
+  epggrab_module_ota_t *m;
+  epggrab_ota_mux_eit_plist_t *plist;
+  eit_private_t *priv, *priv2;
+  int pid, opts;
 
   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;
+
+  priv = NULL;
+  LIST_FOREACH(plist, &om->om_eit_plist, link) {
+    priv2 = (eit_private_t *)plist->priv;
+    if (!priv || priv->module->priority < priv2->module->priority) {
+      m = priv->module;
+      LIST_FOREACH(map, &om->om_modules, om_link) {
+      if (map->om_module == m)
+        break;
+      }
+      if (!map || (!m->enabled && !map->om_forced)) {
+        tvhtrace(m->subsys, "handlers - module '%s' not enabled", m->id);
+        continue;
+      }
+      priv = priv2;
+    }
   }
-  if (map->om_eit_state != EPGGRAB_OTA_MUX_EIT_IDLE) {
-    tvhtrace(m->subsys, "%s - module '%s' already installed", src, m->id);
-    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);
   }
-  map->om_eit_state = state;
 
-  tvhtrace(m->subsys, "%s - detected module '%s'", src, m->id);
+  m = priv->module;
+
+  tvhtrace(m->subsys, "handlers - detected module '%s'", m->id);
   priv = (eit_private_t *)m->opaque;
   pid = priv->pid;
+  opts = 0;
 
   /* Standard (0x12) */
   if (pid == 0) {
@@ -1229,7 +1252,28 @@ static void eit_install_handlers
   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);
+  tvhdebug(m->subsys, "%s: installed table handlers", m->id);
+}
+
+static void eit_queue_priv
+  (mpegts_mux_t *dm, const char *src, eit_private_t *priv)
+{
+  epggrab_ota_mux_t *om;
+  epggrab_ota_mux_eit_plist_t *plist, *plist2;
+
+  om = epggrab_ota_find_mux(dm);
+  if (!om)
+    return;
+
+  LIST_FOREACH(plist2, &om->om_eit_plist, link)
+    if (plist2->priv == priv)
+      return;
+
+  tvhtrace(LS_TBL_EIT, "%s - detected module '%s'", src, priv->module->id);
+  plist = calloc(1, sizeof(*plist));
+  plist->src = src;
+  plist->priv = priv;
+  LIST_INSERT_HEAD(&om->om_eit_plist, plist, link);
 }
 
 void eit_nit_callback
@@ -1267,7 +1311,7 @@ void eit_nit_callback
   if (!priv)
     return;
 
-  eit_install_handlers(dm, priv, "NIT", EPGGRAB_OTA_MUX_EIT_NIT);
+  eit_queue_priv(dm, "NIT", priv);
 }
 
 void eit_sdt_callback(mpegts_table_t *mt, uint32_t sdtpriv)
@@ -1276,12 +1320,6 @@ void eit_sdt_callback(mpegts_table_t *mt, uint32_t sdtpriv)
   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(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);
 
@@ -1308,7 +1346,7 @@ void eit_sdt_callback(mpegts_table_t *mt, uint32_t sdtpriv)
   if (!priv)
     return;
 
-  eit_install_handlers(dm, priv, "SDT", EPGGRAB_OTA_MUX_EIT_SDT);
+  eit_queue_priv(dm, "SDT", priv);
 }
 
 static void _eit_scrape_clear(eit_module_t *mod)
@@ -1514,6 +1552,7 @@ static void eit_init_one ( const char *id, htsmsg_t *conf )
   ops = calloc(1, sizeof(*ops));
   priv = calloc(1, sizeof(*priv));
   ops->start = _eit_start;
+  ops->stop = _eit_stop;
   ops->done = _eit_done;
   ops->activate = _eit_activate;
   ops->process_data = _eit_process_data;
index 917741974eeae3b4f3b0a5219843fa86b47f684d..6e16c82abfcc17865d39e1d1ab9e9104b6c2c23c 100644 (file)
@@ -113,6 +113,15 @@ epggrab_ota_timeout_get ( void )
   return timeout;
 }
 
+static void
+epggrab_ota_free_eit_plist ( epggrab_ota_mux_t *ota )
+{
+  epggrab_ota_mux_eit_plist_t *plist;
+
+  while ((plist = LIST_FIRST(&ota->om_eit_plist)) != NULL)
+    free(plist);
+}
+
 static int
 epggrab_ota_queue_one( epggrab_ota_mux_t *om )
 {
@@ -209,6 +218,9 @@ epggrab_ota_done ( epggrab_ota_mux_t *om, int reason )
   assert(om->om_q_type == EPGGRAB_OTA_MUX_ACTIVE);
   TAILQ_REMOVE(&epggrab_ota_active, om, om_q_link);
   om->om_q_type = EPGGRAB_OTA_MUX_IDLE;
+  LIST_FOREACH(map, &om->om_modules, om_link)
+    if (map->om_module->stop)
+      map->om_module->stop(map, mm);
   if (reason == EPGGRAB_OTA_DONE_STOLEN) {
     /* Do not requeue completed muxes */
     if (!om->om_done && om->om_requeue) {
@@ -274,13 +286,13 @@ epggrab_ota_start ( epggrab_ota_mux_t *om, mpegts_mux_t *mm )
         break;
       }
   }
+  epggrab_ota_free_eit_plist(om);
   LIST_FOREACH(map, &om->om_modules, om_link) {
     map->om_first    = 1;
     map->om_forced   = 0;
     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
@@ -777,6 +789,7 @@ epggrab_ota_load_one
   tvhtrace(LS_EPGGRAB, "loading config for %s", mm->mm_nicename);
 
   ota = calloc(1, sizeof(epggrab_ota_mux_t));
+  LIST_INIT(&ota->om_eit_plist);
   ota->om_mux_uuid = mm->mm_id.in_uuid;
   if (RB_INSERT_SORTED(&epggrab_ota_all, ota, om_global_link, om_id_cmp)) {
     free(ota);
@@ -895,6 +908,7 @@ epggrab_ota_free ( epggrab_ota_head_t *head, epggrab_ota_mux_t *ota  )
     free(map);
   }
   free(ota->om_force_modname);
+  epggrab_ota_free_eit_plist(ota);
   free(ota);
 }
 
index 8b32c5b0f1769bbae3441deec0b192e49762a3a5..47a7c949a8b9186087e717b791ff66717f8dd660 100644 (file)
@@ -100,6 +100,7 @@ epggrab_module_ext_t *epggrab_module_ext_create
 
 typedef struct epggrab_ota_module_ops {
     int (*start)     (epggrab_ota_map_t *map, struct mpegts_mux *mm);
+    int (*stop)      (epggrab_ota_map_t *map, struct mpegts_mux *mm);
     int  (*activate) (void *m, int e);
     void (*done)     (void *m);
     int  (*tune)     (epggrab_ota_map_t *map, epggrab_ota_mux_t *om,